Jump to content
IGNORED

Why would jzintv quit?


Recommended Posts

As long as your project is in development, I'd recommend to run in debug mode with history enabled even if you just want to play the game without using any other specific debugging feature. This is useful for post-mortem analysis.

Link to comment
Share on other sites

11 hours ago, atari2600land said:

I'm making a game and sometimes the emulator just shuts off. What am I doing wrong? What are the possible reasons this would happen?


Check your GOTOs, make sure they are not going off into the weeds.

 

10 hours ago, Arnauld said:

As long as your project is in development, I'd recommend to run in debug mode with history enabled even if you just want to play the game without using any other specific debugging feature. This is useful for post-mortem analysis.


I think the lack of exposure to the debugger and its features, is something that haunts many IntyBASIC programmers when trying to troubleshoot their programs.

 

The focus on Assembly Language and Hexadecimal values can be intimidating, for sure.  Even with the “source-level debugging” integration with IntyBASIC, there is no escaping the complexity for those not used to working with the assembler — e.g., the symbol names are mangled, the register values are in Hexadecimal, the labels and constants do not translate directly, etc.

 

I’ve toyed with the idea of preparing a series of short videos to illustrate how to use the most useful and basic features of the debugger.  I may do that if there is interest.

 

     dZ.

Link to comment
Share on other sites

I set up my Portable Intellivision Development Environment to automate the following command-line parameters at assemble-time:

 

-j [romfile].smap
-s [romfile].sym
-l [romfile].lst
-o [romfile].bin
[main].asm

 

and to automate the following command-line parameters at run-time:

 

--src-map=[romfile].smap
--sym-file=[romfile].sym
--script=dbscript.txt
--debugger

 

This creates additional files that will allow you to see lines of your IntyBASIC source code in the debugger.  jzIntv also likes your terminal window to be at least 160 characters wide, and you might want to automate that as well with a script file (which I named dbscript.txt) containing the following lines:

 

> 160
r

 

The first line tells jzIntv that your terminal window is 160 characters wide.  The second line runs jzIntv automatically.  Normally, when you open jzIntv with the --debugger switch, it waits for you to start running emulation with the command "r".

Link to comment
Share on other sites

11 minutes ago, Zendocon said:

I set up my Portable Intellivision Development Environment to automate the following command-line parameters at assemble-time:

 

-j [romfile].smap
-s [romfile].sym
-l [romfile].lst
-o [romfile].bin
[main].asm

 

and to automate the following command-line parameters at run-time:

 

--src-map=[romfile].smap
--sym-file=[romfile].sym
--script=dbscript.txt
--debugger

 

This creates additional files that will allow you to see lines of your IntyBASIC source code in the debugger.  jzIntv also likes your terminal window to be at least 160 characters wide, and you might want to automate that as well with a script file (which I named dbscript.txt) containing the following lines:

 

> 160
r

 

The first line tells jzIntv that your terminal window is 160 characters wide.  The second line runs jzIntv automatically.  Normally, when you open jzIntv with the --debugger switch, it waits for you to start running emulation with the command "r".

 

If you use the IntyBASIC SDK, that is handled for you automatically.  The command "intybuild" will set up set up the symbol and map files, and the command "intydbug" will run the debugger.  You break to the debugger while running the program using F4, or you can add "-s" in the command line for "intydbug" to start the program in the debugger console.

 

     -dZ.

Link to comment
Share on other sites

As for the debugger, the F4 key pauses emulation, and the debugger takes over.  For a list of commands, type "?"

 

Commands I use often are:


w [RAM address (range size)]: Watch for a change to a particular memory address or range of addresses.  The terminal window will display a message when a change occurs, along with the ROM address which triggered the change.  Using this command a second time on the same address turns off watching.

 

b [ROM address]: Break to the debugger when code execution reaches the specified address.

 

n [ROM address]: A negation of the previous command.  Stop breaking to the debugger when code execution reaches the specified address.

 

s [number of commands]: Step through the specified number of CPU commands.  "s" by itself steps only through 1 command.

 

t [number of commands]: Same as above, but skips over function calls.

 

r [number of commands]: Run emulation only until the specified number of CPU commands are executed.  "r" by itself runs indefinitely until you press the Break key again (F4).

 

m [RAM address (range size)]: Memory dump.  Display contents of the specified RAM address.  By default, the range size is 64, so if you don't specify a size, you will get the specified address and the next 63 after it.  They are displayed in groups of 8 per line, so if you start at $15d, you'll see $158-15f in the first line, with a '*' after $15d, which you had specified.

 

These are the RAM address ranges:

 

$100-1ef: 8-bit RAM (original games which use Executive ROM start at $15d).

 

$31d-35c: 16-bit RAM (original games which use Executive ROM only have $324, $32c, $334, $33c, $344, $34c, $354, and $35c available for general use).

 

$8000?-9???: 16-bit JLP RAM.  If you enable JLP, your program will use 16-bit RAM in this range.

 

$4000-47ff: 8-bit ECS RAM.  Chances are, your program doesn't utilize this, even if you use ECS.


$360-fff: 16-bit Tutorvision RAM.  Chances are, your program doesn't utilize this.  By default, these address are frozen to a value of -1, so if I want to autodetect whether or not extra Tutorvision RAM is available, I try to set one of the addresses to 0 and check for a 0 value at that same address.

Edited by Zendocon
Additional information about ECS and Tutorvision RAM address ranges
Link to comment
Share on other sites

1 minute ago, DZ-Jay said:

 

If you use the IntyBASIC SDK, that is handled for you automatically.  The command "intybuild" will set up set up the symbol and map files, and the command "intydbug" will run the debugger.  You break to the debugger while running the program using F4, or you can add "-s" in the command line for "intydbug" to start the program in the debugger console.

 

     -dZ.

 

Ah yes, the IntyBASIC SDK.  That's a good one too.

 

Since my Portable Intellivision Development Environment and its Graphical Suite, PIDEGS, is a sort of competitor, I've never used that myself.  Both are good tools for serious developers.  My advertised advantage is that my PIDE runs on Android, and I prefer carrying around a tablet for development on-the-go instead of a laptop.

Link to comment
Share on other sites

I wonder if Chris interleaves code with data, subroutines to GOSUB or even GOTO after data blocks. From previous sneak peeks of his code, it seems to happen. If so, I would strongly recommend try to order everything so you have code in one sequence of routines, then your data areas. Not that it should matter much, but it reduces possible causes of errors.

Link to comment
Share on other sites

It seems that you are smashing the stack by "printing" to the wrong address.

 

I caught the crash in procedure "new_column1" -- when it ended, it tried to return but got a bogus address from the top of the stack.  It seems that when the following code executed:

new_column1: procedure
	print at ghost1pos,"   "
	print at ghost2pos,"   "
	print at dot1pos, "   " 	
   '  ...

 

The value of "ghost2pos" was pointing beyond the BACKTAB and wrote into the memory reserved for the stack itself.

 

You may want to check the values of your variables.

 

     -dZ.

  • Like 2
Link to comment
Share on other sites

So, a quick inspection of the variables and I see that it is precisely what I suspected:  The variable"ghost2pos" is decremented below zero, turning it into -1 ($FFFF), which is stored in the 8-bit variable as 255 ($FF).  This value is then used in procedure "new_column1" as the BACKTAB offset in which to print, which happens to be outside the range and right smack at the start of the stack.

 

At that point, your program is hopelessly broken, for the next "return" statement will pull a corrupted return address from the stack.

 

The culprit is in the following code in the "main_loop":

	offset_x=offset_x-1
	if offset_x=0 then 
		offset_x=7
		row1timer=row1timer-1
		row2timer=row2timer-1
		row3timer=row3timer-1	
		ghost1pos=ghost1pos-1
		ghost2pos=ghost2pos-1	' <-- some hanky panky afoot here!
		ghost3pos=ghost3pos-1	
		ghost4pos=ghost4pos-1	
		ghost5pos=ghost5pos-1	
		ghost6pos=ghost6pos-1		
		dot1pos=dot1pos-1	
		dot2pos=dot2pos-1	
		dot3pos=dot3pos-1	
	end if


A quick looksie into your code, and I see that the "ghost2pos" is only assigned a new value in procedure "new_column1" under some specific conditions:

	ghostpattern2=(rand/64)
	ghost2color=3
	if ghostpattern2=0 and ghostpattern1>0 then ghost2pos=19 : ghost2color=0
	if ghostpattern2=1 then ghost2pos=99
	if ghostpattern2=2 then ghost2pos=119
	if ghostpattern2=3 then ghost2pos=139

 

Intuitively, I see a flaw right there:  If both "ghostpattern2" and "ghostpattern1" happen to be zero at the same time -- which is a distinct possibility -- then the first condition will return false, and "ghost2pos" will not be updated.  Moreover, if at that point "ghost2pos" happens to be zero, it will be decremented to a negative value, leading to some mischief.

 

This explains the observed behaviour.  It also explains why it appears to be random:  the conditions themselves are driven by the values of "rand."

 

Honestly, the above analysis is based on my superficial view of your code's behaviour -- I have not analyzed your program to understand what those variables do, nor how it all works in practice.  I hope the description of the problem at least gives you an idea for how to solve it.

 

At minimum, I would suggest guarding against negative values when decrementing a variable.  Also, you should ensure that "ghost2pos" always gets a valid value by guaranteeing that every condition that leads to its update is accounted for.

 

Let me know if you need further help or if any of the above does not make sense.

 

     -dZ.

Link to comment
Share on other sites

3 hours ago, atari2600land said:

I think I understand what is going on. Honestly, I don't know what I was thinking when I wrote that code.

 

No worries.  Let me know if you need any more help.

 

     -dZ.

Link to comment
Share on other sites

11 minutes ago, carlsson said:

Good catch!

 

Though, shouldn't the PRINT AT function take the value modulo the size of BACKTAB, or is it a design choice that you can write data to any subsequent address using PRINT?

@nanochess might know if it is a design feature or not.

 

I do not think it is a feature.  For one thing, it adds $200 automatically, so it seems designed to work for values in the System RAM area, which includes the BACKTAB and ... the CPU stack.  Because IntyBASIC abstracts away the stack and all its internal memory, it seems weird to me that someone would provide a feature that would allow for such a clumsy accident to occur on purpose.

 

More likely, it is just an optimization to avoid the cost of checking for bounds.  In fact, the manual says so explicitly:

Quote

PRINT [AT [expr]][COLOR [expr]][,]"string"[,"string"]

       ...

 

    Notice that the cursor position is not limited so you can write outside
    of the screen and this will make your program crash!

 

So ... I guess like with many other common problems, it could be solved by a simple rule:  RTFM. 😄

 

     -dZ;

Link to comment
Share on other sites

2 hours ago, carlsson said:

Good catch!

 

Though, shouldn't the PRINT AT function take the value modulo the size of BACKTAB, or is it a design choice that you can write data to any subsequent address using PRINT?

@nanochess might know if it is a design feature or not.

There are no boundary checkings done in PRINT AT.

 

IntyBASIC trusts the programmer :grin: basically this is to save an expensive comparison that would use also precious words in ROM.

 

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...