The Universal Atari Disassembler
Universal 680x0 and DSP 56k disassembler for Atari binaries.
.P56, Motorola .LOD,
COFF .OUT, cooked DSP blocks) and mixed-mode embedded microkernels in 680x0
executables. Features indirect jump table detection and symbolic reconstruction, hardware DO loop analysis,
on-chip peripheral annotations, and execution cycle timing.
rg-asm --no-opt-size (680x0)
and rg-dsp-asm (DSP56001), tested against a large range of Atari binaries.
VT52_ smart labels.
a.out, plus external .sym
sidecars for raw images.
.ST, .MSA, and Pasti .STX
disk images — ideal for custom loaders, demos, and games.
--inspect disk)
across .ST, .MSA, and Pasti .STX floppy images.
.ZIP, .LZH, or floppy disk images in memory without unpacking
them first.
--annotate-cycles) dynamically calculated for 68000, 68030, and DSP56001 architectures.
.TOS/.PRG executables,
standalone DSP binaries (.P56, .LOD, .OUT, cooked),
ELF objects, DRI/GST relocatables, VBCC a.out, static .a libraries, and
raw binary dumps.
$ rg-dis GAME.TOS █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · m68k disassembler ✓ Disassembling GAME.TOS (564,066 bytes) ✓ Disassembled 564,066 bytes in 1.69s _start: MOVE.L 4(A7),A5 ; basepage pointer MOVE.L $0C(A5),D0 ; text size ADD.L $14(A5),D0 ; data size ADD.L $1C(A5),D0 ; bss size ADDI.L #$0100,D0 ; basepage header (256 bytes) MOVE.L D0,-(A7) ; newsiz - new size in bytes MOVE.L A5,-(A7) ; block - start of block to shrink CLR.W -(A7) ; zero - reserved, must be 0 MOVE.W #74,-(A7) ; Mshrink - shrink a memory block TRAP #1 ; GEMDOS #74 (Mshrink) LEA $C(A7),A7 CLR.L -(A7) ; Super(0) -> enter supervisor mode MOVE.W #32,-(A7) ; GEMDOS #32 (Super) TRAP #1 ; GEMDOS #32 -> D0 = old SSP LEA 6(A7),A7 MOVE.W #$0000,($FFFF8240).W ; write palette[0] MOVE.B #$00,($FFFF8260).W ; sshiftmod - ST low resolution … $
$ rg-dis --annotate-cycles GAME.TOS █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · m68k disassembler ✓ Disassembling GAME.TOS with --annotate-cycles (68000) ✓ Disassembled 564,066 bytes in 1.69s _start: MOVE.L 4(A7),A5 ; 16 | basepage pointer MOVE.L $0C(A5),D0 ; 16 | text size ADD.L $14(A5),D0 ; 18 | data size ADD.L $1C(A5),D0 ; 18 | bss size ADDI.L #$0100,D0 ; 16 | basepage header (256 bytes) MOVE.L D0,-(A7) ; 12 | newsiz - new size in bytes MOVE.L A5,-(A7) ; 12 | block - start of block to shrink CLR.W -(A7) ; 14 | zero - reserved, must be 0 MOVE.W #74,-(A7) ; 12 | Mshrink - shrink a memory block TRAP #1 ; 34 | GEMDOS #74 (Mshrink) LEA $C(A7),A7 ; 8 | CLR.L -(A7) ; 20 | Super(0) -> enter supervisor mode MOVE.W #32,-(A7) ; 12 | GEMDOS #32 (Super) TRAP #1 ; 34 | GEMDOS #32 -> D0 = old SSP LEA 6(A7),A7 ; 8 | MOVE.W #$0000,($FFFF8240).W ; 16 | write palette[0] MOVE.B #$00,($FFFF8260).W ; 16 | sshiftmod - ST low resolution … $
$ rg-dis AUDIO_FX.P56 █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · dsp disassembler ✓ Disassembling AUDIO_FX.P56 (3 memory spaces: P, X, Y) ✓ Disassembled 1,420 words in 12ms ; --- P program space: Org $0040 (214 words) --- org P:$0040 start: movec #0,SP move #$0000,OMR ; normal expanded operating mode move #$FFEB,R0 ; Host Interface: HSR / status register bclr #0,X:(R0) ; clear receive byte flag move #$003F,M1 ; circular buffer modulo 64 move #_jump_table,R2 ; dispatch table in Y data space move Y:(R2)+,R3 jmp (R3) ; indirect jump via jump table _process: do #64,_end_fft ; hardware DO loop (64 iterations) mpy X0,Y0,A X:(R1)+,X0 Y:(R4)+,Y0 macr -X1,Y1,A X:(R2)+,X1 Y:(R5)+,Y1 _end_fft: ; end of DO loop from P:$004E rts ; --- Y data space: Org $1000 (dispatch table) --- org Y:$1000 _jump_table: dc _handler_init ; P:$0060 (reconstructed target) dc _handler_process ; P:$0074 (reconstructed target) dc _handler_exit ; P:$0092 (reconstructed target) $
$ rg-dis GAME.TOS █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · mixed-mode disassembler ✓ Disassembling GAME.TOS (68030 + embedded DSP microkernels) ✓ Disassembled 564,066 bytes in 1.72s _init_dsp_subsystem: PEA _dsp_kernel(PC) ; prg - DSP microkernel pointer MOVE.W #1,-(A7) ; ability - DSP program identifier MOVE.W #109,-(A7) ; Dsp_ExecProg - execute DSP program TRAP #14 ; XBIOS #109 (Dsp_ExecProg) LEA 8(A7),A7 RTS ; --- Embedded Falcon DSP Microkernel (P program space, Org $0040) --- _dsp_kernel: pushcpu 56001, packed, noeven org P:$0040 _dsp_start: move #$FFE0,R0 ; Host Interface: PBC (Port B Control) movep #1,X:(R0) ; enable host interface do #128,_dsp_mix_loop ; audio mixing pipeline move X:(R1)+,A add Y0,A Y:(R2)+,Y0 move A,X:(R3)+ _dsp_mix_loop: ; end of DO loop from P:$0046 rts popcpu ; --- End of embedded DSP block (resuming 68030) --- _resume_68k: MOVE.W #$2300,SR ; restore status register RTS $
$ rg-dis --inspect disk DEMO.ST █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · disk inspector ✓ Inspected DEMO.ST (80 tracks, 2 sides, 9 spt) disk image · ST · 80 tracks (0-79), 2 sides, 9 sectors/track ┌────────────┬──────────────────┐ │ property │ value │ ├────────────┼──────────────────┤ │ container │ ST │ │ image size │ 737,280 bytes │ │ sectors │ 1,440 │ │ format │ TOS/FAT12 volume │ └────────────┴──────────────────┘ boot sector · checksum 0xB57B · not executable ┌──────────┬─────────────────────────────────────┐ │ property │ value │ ├──────────┼─────────────────────────────────────┤ │ checksum │ 0xB57B │ │ bootable │ no │ │ media │ 0xF9 — 720 KB double-sided 3.5-inch │ │ serial │ 0x47444258 │ └──────────┴─────────────────────────────────────┘ files · 1 file(s) · 1 folder(s) · 0 deleted ┌──────────────┬─────────┬────────────┬──────┬─────────────────────┐ │ path │ size │ date │ attr │ notes │ ├──────────────┼─────────┼────────────┼──────┼─────────────────────┤ │ AUTO/ │ │ 2001-10-14 │ D │ │ │ GAME.PRG │ 646,030 │ 2001-10-14 │ A │ executable (GEMDOS) │ └──────────────┴─────────┴────────────┴──────┴─────────────────────┘ $
$ rg-dis --inspect strings GAME.TOS █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · string extractor ✓ Extracted strings from GAME.TOS (min score: 40, code regions excluded) ┌─────────────────────────┬────────────┬──────┬─────┬─────┬─────────────────────┐ │ string │ addr │ seg │ len │ ref │ label │ ├─────────────────────────┼────────────┼──────┼─────┼─────┼─────────────────────┤ │ PRESS FIRE TO START │ 0x000425DC │ DATA │ 19 │ Y │ STR_PRESS_FIRE │ │ PLAYER ONE READY │ 0x000425F8 │ DATA │ 16 │ Y │ STR_PLAYER_ONE │ │ HIGH SCORE TABLE │ 0x00042604 │ DATA │ 16 │ Y │ STR_HIGH_SCORE │ │ GAME OVER │ 0x0004268C │ DATA │ 9 │ Y │ STR_GAME_OVER │ │ BONUS STAGE COMPLETED │ 0x00042614 │ DATA │ 21 │ Y │ STR_BONUS_STAGE │ │ LEVEL SELECT │ 0x000426C0 │ DATA │ 12 │ Y │ STR_LEVEL_SELECT │ │ ENTER YOUR INITIALS │ 0x00071AE8 │ DATA │ 19 │ Y │ STR_ENTER_INITIALS │ └─────────────────────────┴────────────┴──────┴─────┴─────┴─────────────────────┘ $
$ rg-dis --bootsector CUDDLY.MSA █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · bootsector disassembler ✓ Extracted bootsector from CUDDLY.MSA (checksum $1234, executable) ✓ Disassembled 512 bytes in 80ms BRA.S _L0020 dc.w $001E,$E5E5,$E5E5,$0000,$0000,$0202,$0100… _L0020: MOVE.W #14,D0 LEA ($FFFF8242).W,A0 ; read palette[1] _L0028: CLR.W (A0)+ DBRA D0,_L0028 MOVE.B #2,($484).W ; set conterm (keyclick=off, repeat=on) LEA ($040000).L,A7 PEA _L012A(PC) MOVE.L (A7)+,($4D2).W ; write _vbl_lis[1] MOVEM.W _L011A(PC),D0-D3 LEA ($070000).L,A0 BSR.W _L00F0 … _L00F0: MOVE.W D0,-(A7) ; count - sector count MOVE.W D1,-(A7) ; sideno - side number MOVE.W D2,-(A7) ; trackno - track number MOVE.W D3,-(A7) ; sectno - first sector number CLR.W -(A7) ; devno - floppy drive number, 0 = A CLR.L -(A7) ; filler - reserved, must be 0 PEA (A0) ; buf - transfer buffer pointer MOVE.W #8,-(A7) ; Floprd - read floppy sectors TRAP #14 ; XBIOS #8 (Floprd) LEA $14(A7),A7 RTS $
$ rg-dis --inspect functions,cycles GAME.TOS █▀▀▄ █▀▀▀ █▀█▄ █ ▀█ RESERVOIR GODS ▀ ▀ ▀▀▀▀ rg-dis 0.10.4 · m68k disassembler ✓ Inspected GAME.TOS ┌─────────────────────┬────────┬──────────────┐ │ function │ bytes │ 68000 cycles │ ├─────────────────────┼────────┼──────────────┤ │ _start │ 60 │ 232 │ │ _main │ 148 │ 620 │ │ @Input_ProcessIKBD │ 68 │ 254 │ │ @Font_ShowInfo │ 700 │ 2606 │ │ @Editor_TaskUpdate │ 564 │ 1782 │ ├─────────────────────┼────────┼──────────────┤ │ total │ 451660 │ 1805784 │ └─────────────────────┴────────┴──────────────┘ $
rg-dis game.tos -o game.s # disassemble executable → .s rg-dis game.tos --annotate-cycles -o game.s # per-instruction CPU cycle costs rg-dis dsp_prog.p56 # disassemble DSP56001 binary (.p56 / .lod / .out) rg-dis game.tos --inspect embedded-dsp # scan Falcon binary for embedded DSP microkernels rg-dis game.tos --inspect cpu # minimum CPU & FPU requirements rg-dis game.tos --inspect functions,cycles # function sizes & 68000 cycles rg-dis game.tos --inspect strings # scored string extraction rg-dis cuddly.msa --bootsector # extract & disassemble boot block rg-dis cuddly.msa # floppy image: auto-routed to the disk pipeline rg-dis game.st --disk 10/0/1..10/1/9 # floppy track & sector range rg-dis AUTO/GAME.PRG --container game.msa # direct in-container extraction rg-dis tos.img --org 0xFC0000 --sym tos.sym # ROM image with DRI/GST symbol map
After unzipping, check the extracted files (the archive includes SHA256SUMS):
sha256sum -c SHA256SUMS