Jump to content
IGNORED

Part 4 - CDFJ Debugging with Stella


SpiceWare

Recommended Posts

Stella has excellent support for developers, you can read about it in the Stella documentation in the sections:

 

 

Stella does not directly support the debugging of ARM code; however, we can use the extra cartridge tabs to view information before and after the ARM code has run, which can be helpful to track down problems.

Note: I'm only going to show Stella's Debugger as it pertains to CDFJ, if you're unfamiliar with using it then read over these to help get you up to speed:

 

  • Reply 9 - use Stella to create a disassembly
  • Reply 12 - use Stella to help with cycle counts
  • Reply 2 - Fixed Debug Colors mode
  • Video tutorial by @tschak909
  • if you know of a helpful resource not listed then add a comment with a link

 

 

Cartridge CDFJ tab

 

Just a brief overview of the CDFJ bank switching scheme.  Games using the original CDF spec, such as Draconian and Super Cobra Arcade, will have slightly different text to denote they're using an older version of the scheme.
 

1920913498_ScreenShot2019-12-17at8_33_53AM.thumb.png.2dc40d766ff64f11340b254cba0eb26a.png

 

 

 

States tab

 

Status of the various CDFJ registers. Before your initialization routine runs the values will not be valid:

 

34408666_ScreenShot2019-12-17at8_33_57AM.thumb.png.4d10d1f96566abecf4ae3866af3b4c2f.png

 

An example after the values have been initialized.

 

667980776_ScreenShot2019-12-18at9_10_47PM.thumb.png.5be334d589909b67bc6b17ba50d0ddcc.png

 

Like the CartridgeCDFJ tab, the States tab will be slightly different for older CDF games.

 

 

 

Cartridge RAM tab

 

The Cartridge RAM tab shows the entire 8K of RAM that's available in the Harmony/Melody.  The first 2 K contain the CDFJ driver, so  should be ignored.  The first 2K also contain the various registers, but those are much easier to view on the States tab.

 

659375189_ScreenShot2019-12-17at8_34_43AM.thumb.png.a14a378b8b875a91385ed191d4326795.png

 

You can scroll down Description box for a little more info:

 

60557891_ScreenShot2019-12-17at8_34_50AM.thumb.png.848ae6721c0c4d8a39584d219193e799.png

 

 

 

Display Data

 

As mentioned in Part 1, ARM RAM begins at 0x40000000 and Display Data begins at 0x40000800. Stella's debugger drops off the leading 0x4000 so if we scroll down to 08xx we'll be at the start of Display Data RAM:

 

533482477_ScreenShot2019-12-17at8_40_22AM.thumb.png.83ac4ee7a24377b0025caa2a56724339.png

 

The initial values in Display Data RAM are random, so the 6507 InitSystem routine will call our C function Initialize() to zero it out so we have a known starting state:

781980017_ScreenShot2019-12-17at8_41_07AM.thumb.png.8824fae7df15b7a5c86e7f2f48f4e990.png

 

In the 6507 code the first part of Display Data is defined as this:

_DS_TO_ARM:     
_RUN_FUNC:  ds 1        ; function to run
_SWCHA:     ds 1        ; joystick directions to ARM code
_SWCHB:     ds 1        ; console switches to ARM code
_INPT4:     ds 1        ; left firebutton state to ARM code
_INPT5:     ds 1        ; right firebutton state to ARM code

_DS_FROM_ARM:           ; ARM OverScan routines return value for MODE
_MODE:                  ; $00 = splash, $01 = menu, $80 = game 
_BALL_X:    ds 1        ; ARM VerticalBLank routines do not return MODE, instead
_M1_X:      ds 1        ; theyreturn values for the 5 X positions
_M0_X:      ds 1
_P1_X:      ds 1
_P0_X:      ds 1

; Splash screen datastreams
_SPLASH0:   ds 192
...

If we look into the symbol file collect3.sym we can find the values for each label:

 

_BALL_X                  0005                  
_DS_FROM_ARM             0005                  
_DS_TO_ARM               0000              (R )
_INPT4                   0003                  
_INPT5                   0004   
_M0_X                    0007                  
_M1_X                    0006                  
_MODE                    0005                  
_P0_X                    0009                  
_P1_X                    0008                  
_RUN_FUNC                0000                  
_SPLASH0                 000a                  
_SWCHA                   0001                  
_SWCHB                   0002                  

 

To see them in the CartridgeRAM tab just add 0x0800 to the value.   If we advance a single frame we'll see the RAM starting at 0x0800 change:

1139264175_ScreenShot2019-12-17at8_47_24AM.thumb.png.0210113c22591fef38fc93fe9eef34b0.png

 

So we can see the following values in RAM are:

  • 05 = _RUN_FUNC
  • ff = _SWCHA
  • 3f = _SWCHB
  • 8c = _INPT4
  • 8d = _INPT5

 

 

Advance a few more frames until we see SPLASH in the TIA Display in the upper-left:

1666276870_ScreenShot2019-12-17at8_47_51AM.thumb.png.e37753dda8241844757db28530d8cee9.png

 

From here we can see:

  • _P1_X at address 08 has the value of 48
  • _P0_X at address 09 has the value of 40
  • _SPLASH0 staring at address 0a is filled in with the graphics to show SPLASH down the screen.

 

If we switch to the TIA tab on the left we can see the positions of the players:

 

1355912832_ScreenShot2019-12-17at9_02_34AM.thumb.png.ff0d06b472c01e9a84c536943ef69108.png

 

  • P0 Pos# = 64
  • P1 Pos# = 72

 

At first glance those look incorrect, but the Pos# values are shown in decimal while the RAM values are shown in hexadecimal.  64 = $40 and 72 = $48, so they do match.

 

 

 

C Variables and Stack

 

C Variables and Stack begin at 0x40001800

 

Global variables are those defined outside of functions. In Collect 3 those are currently:

unsigned int frame;
unsigned char player_x[2];
unsigned char player_y[2];
unsigned short int player_shape[2];

 

We can use the Map file to find their RAM address.  The Map file for Collect 3 is main/bin/testarm.map

 

At the start of the map file we will find a list of the variables and their sizes:

Common symbol       size              file

player_y            0x2               main.o
frame               0x4               main.o
player_x            0x2               main.o
player_shape        0x4               main.o

 

Their addresses can be found towards the end of the file:

 COMMON         0x0000000040001808        0xe main.o
                0x0000000040001808                player_y
                0x000000004000180c                frame
                0x0000000040001810                player_x
                0x0000000040001812                player_shape

 

1445987503_ScreenShot2019-12-17at9_34_45AM.thumb.png.4a933018a9aa807a98e18280673bd9aa.png

 

The ARM uses LSB order so looking at the table we see our frame counter is at 180c which contains the bytes de 02 00 00 which is the value $000002de or 734

The values for the 2 byte array player_x are at 1810 and contain the bytes 24 and 74, which are 36 and 116 respectively.  If we switch to the TIA tab we can see the Pos # for P0 and P1 match.

 

1914977880_ScreenShot2019-12-18at9_25_56PM.thumb.png.7d5930a2aefde06c029d7ac0ff7d7f3c.png

 

If we switch to the I/O tab we can check the joystick positions then click the Frame +1 button to advance a frame. We'll see the values for player_x and player_y both changed:

 

2074061960_ScreenShot2019-12-17at9_35_01AM.thumb.png.88a78887e068d82140ee856bbe9a440e.png

 

However, when we look at the TIA tab the Position numbers have not yet changed:

 

1161936560_ScreenShot2019-12-18at9_27_20PM.thumb.png.e27fd4c2522a8fd3a0deebe43a620455.png

 

That's because the values for player_x and player_y were changed in Overscan and we've not yet run Vertical Blank which is when the positioning of the players occurs.  Click Frame +1 again and the positions will change.

 

548581637_ScreenShot2019-12-18at9_27_27PM.thumb.png.ff7441ba4d442fa48158fd34bb19c8f8.png

 

The 4 bytes at 1800-1803 are from the random number generator.  It uses a static variable within the function:

 

unsigned int getRandom32() {
  // using a 32-bit Galois LFSR as a psuedo random number generator.
  // http://en.wikipedia.org/wiki/Linear_feedback_shift_register#Galois_LFSRs
  static unsigned int random = 0x02468ace;
  return random = (random >> 1) ^ (unsigned int)(-(random & 1u) & 0xd0000001u);
}

 

which for some reason it does not appear in the Map file.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 5 months later...
On 12/17/2019 at 6:37 AM, SpiceWare said:

 

1445987503_ScreenShot2019-12-17at9_34_45AM.thumb.png.4a933018a9aa807a98e18280673bd9aa.png

 

The ARM uses LSB order so looking at the table we see our frame counter is at 180c which contains the bytes de 02 00 00 which is the value $000002de or 734

It would be a useful feature if Stella allowed you to highlight 1, 2, or 4 bytes in the Cartridge Ram, and it displayed the the result in MSB order for both hex and decimal. The debugger has also changed format with the latest release so it is shorter in height, and the "label", "dec", and "bin" are gone on the cartridge ram. However I think something like I mocked below could work. What do you guys think? I suppose the length of the box for decimal would need to increase, but that shouldn't be a show stopper.

 

mockup.thumb.png.932165f6395182d7dab079d3258ed0bc.png

 

 

 

  • Like 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

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