Navigate Site: | Home | Blog | Samples | Downloads | About Us | Links | Documentation

Frodo/SuperSAM

About SuperSAM

SuperSAM is an enhanced version of the SAM (Simple Assembler / Monitor) that comes with the C64 emulator Frodo.

We picked Frodo because it was an early favourite of the developer's, and easy to modify.

Run Frodo/SuperSAM and we'll walk you through it.

The first thing you'll see is 2 windows. One is the main Frodo window (title bar says 'Frodo - Frodo'). The 2nd window says 'Dialog' and has the text 'SuperSAM Log' in it. The 2nd window cannot be resized, and isn't very big, but still does its job, which is to display reads, writes, and function executions as they occur.

Using the 'w' operation

Go to menu Tools and 'Load Snapshot'. Select 'zol.fss' and click 'Open'.

Press space to start Escape from Zol.

Go to menu Tools and select 'SAM'. Enter 'w d1' and hit enter, then 'x' and hit enter to return.

According to zol.lookup.lisp, (209 . "TileUnderCursor") means d1 is 'TileUnderCursor'.

To see this, get the log window on the right, with Frodo on the left half of the screen.

Now, move the cursor around with Q,A,O,P, and see this scroll up in the log window:

It means that the address was $D1/209. The code address writing to D1/209 is at $1d22. The byte field says what value is being written to D1. In other words, the tile under the cursor is 46/$2E ('Magic Wood').

Code Interleaving

The basic idea is similiar to Visual Studio's debugger. An interleave code file looks like this:

void DrawBorderTile(int Arg_acc) {
17217
int LLocal1;
17217
Global_135 = Arg_acc;
17219
usub_4313();
17223
LLocal1 = 7;
17224
do {
17226
        *(GUI_Draw_Pointer)[LLocal1] = *(Global_18)[LLocal1];
17228
        LLocal1 = (LLocal1 - 1);
17229
} while (LLocal1 >= 0);//LoopEndWh 434D
17235
*(Redraw_PointerToColourMap)[0] = BorderDrawParamColour;
17237
return;// 4355
};

Go to menu Tools and 'Load Snapshot'. Select 'zol.fss' and click 'Open'.

Press space to start Escape from Zol.

Go to menu Tools and select 'SAM'.

Type in: 'D zol.usub_4341.txt.code.txt' and hit Enter.

Type in 'd 4341'.

C64> d 4341
***int LLocal1;
***Global_135 = Arg_acc;
4341: 85 87     sta 87
***usub_4313();
4343: 20 13 43  jsr 4313
***LLocal1 = 7;
4346: a0 07     ldy #07
***do {
4348: b1 12     lda (12),y
***     *(GUI_Draw_Pointer)[LLocal1] = *(Global_18)[LLocal1];
434a: 91 04     sta (04),y
***     LLocal1 = (LLocal1 - 1);
434c: 88        dey
***} while (LLocal1 >= 0);//LoopEndWh 434D
434d: 10 f9     bpl 4348
434f: a5 85     lda 85
4351: a0 00     ldy #00
****(Redraw_PointerToColourMap)[0] = BorderDrawParamColour;
4353: 91 06     sta (06),y
***return;// 4355
4355: 60        rts

Decompiled code is on the line before the original assembly code.

The Rest of the SuperSAM Commands

There are a few key functions:

Key SuperSAM description Documentation
< Set refuse-write from here up This lets you (combined with >) stop the CPU being able to write to this range of addresses
> Set refuse-write from here down See above
! Add read log point to list (no arg clears list) This keeps a record/list of all reads from this address. It also logs them to the LOG window.
w Add write log point to list (no arg clears list) This keeps a record/list of all writes to this address. It also logs them to the LOG window.
$ Add execute log point to list (no arg clears list) This keeps a record/list of all executions of this address. It also logs them to the LOG window.
U Old/new value pokefinder As it says above.
u +/- 1 pokefinder As it says above
D "file" Load up interleaved decompile dump In English takes the form, eg sample dump:
  • void MainMenu() {
  • 19585
  • Global_90 = 1;
  • 19587
  • usub_1CFB();
  • 19605
  • usub_1D9A();
This indicates that that address (19585) is the start of the Global_90 = 1.

This is handy when the disassembler is 'interleave aware', and can, as SuperSAM can, interleave the disassembly with the addresses.

Shown in SuperSAM's disassembler:

  • C64> d 4c7e
  • 4c7e: 78 sei
  • 4c7f: a9 01 lda #01
  • ***Global_90 = 1;
  • 4c81: 85 5a sta 5a
  • ***usub_1CFB();
  • 4c83: 20 fb 1c jsr 1cfb

J Show last 4 JSR's As it says above
R Reset JSR count Sets all JSR counts to 0
I [choice] [start] [end] Show functions with JSR count >0 in memory range (default choice=0 start=0 end=ffff). I on its own shows ALL calls >=1 and otherwise, shows you functions executed N times.
N/A Call stack shows 1:caller 2:caller of 1 3:caller of 2 Just a note