💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › action › Ribbit%20(4am%2… captured on 2023-05-24 at 23:04:34.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

-----------------Ribbit----------------
A 4am crack                  2014-06-14
---------------------------------------

"Ribbit" is a 1982 arcade game written
by C. Eisnaugle and L. Fortnow, and
distributed by Piccadilly Software Inc.

The original disk immediately switches
to the hi-res graphics page and
progressively displays a title screen
while loading the rest of the game.
Once loaded, the game never touches the
original disk, so it may be possible to
capture this game as a single file.

COPYA fails miserably and immediately
with a disk read error. EDD 4 bit copy
fares no better; read errors everywhere
and the copy seems like it never even
gets past track 0.

Time for boot tracing with AUTOTRACE.

[S6,D1=original disk]
[S5,D1=my work disk]

]PR#5
...
CAPTURING BOOT0
...reboots slot 6...
...reboots slot 5...
SAVING BOOT0

]CALL -151

*800<2800.28FFM

*801L

0801-   A2 00       LDX   #$00
0803-   BD 00 08    LDA   $0800,X
0806-   9D 00 02    STA   $0200,X
0809-   E8          INX
080A-   D0 F7       BNE   $0803
080C-   4C 0F 02    JMP   $020F

Ooh, exciting. Right off the bat, we're
relocating to a low memory page.

*20F<80F.8FFM

*20FL

; Set up a data table of some sort. But
; why?
020F-   A0 AB       LDY   #$AB
0211-   98          TYA
0212-   85 3C       STA   $3C
0214-   4A          LSR
0215-   05 3C       ORA   $3C
0217-   C9 FF       CMP   #$FF
0219-   D0 09       BNE   $0224
021B-   C0 D5       CPY   #$D5
021D-   F0 05       BEQ   $0224
021F-   8A          TXA
0220-   99 00 08    STA   $0800,Y
0223-   E8          INX
0224-   C8          INY
0225-   D0 EA       BNE   $0211
0227-   84 3D       STY   $3D

; $00 into zero page $26 and $03 into
; $27 means we're probably going to be
; loading data into $0300..$03FF later.
0229-   84 26       STY   $26
022B-   A9 03       LDA   #$03
022D-   85 27       STA   $27
022F-   A6 2B       LDX   $2B
0231-   20 5D 02    JSR   $025D

*25DL

; read a sector from somewhere on track
; 0, using a 4-4 nibble encoding scheme
025D-   18          CLC
025E-   08          PHP
025F-   BD 8C C0    LDA   $C08C,X
0262-   10 FB       BPL   $025F
0264-   49 D5       EOR   #$D5
0266-   D0 F7       BNE   $025F
0268-   BD 8C C0    LDA   $C08C,X
026B-   10 FB       BPL   $0268
026D-   C9 AA       CMP   #$AA
026F-   D0 F3       BNE   $0264
0271-   EA          NOP
0272-   BD 8C C0    LDA   $C08C,X
0275-   10 FB       BPL   $0272
0277-   C9 B5       CMP   #$B5
0279-   F0 09       BEQ   $0284
027B-   28          PLP
027C-   90 DF       BCC   $025D
027E-   49 AD       EOR   #$AD
0280-   F0 1F       BEQ   $02A1
0282-   D0 D9       BNE   $025D
0284-   A0 03       LDY   #$03
0286-   84 2A       STY   $2A
0288-   BD 8C C0    LDA   $C08C,X
028B-   10 FB       BPL   $0288
028D-   2A          ROL
028E-   85 3C       STA   $3C
0290-   BD 8C C0    LDA   $C08C,X
0293-   10 FB       BPL   $0290
0295-   25 3C       AND   $3C
0297-   88          DEY
0298-   D0 EE       BNE   $0288
029A-   28          PLP
029B-   C5 3D       CMP   $3D
029D-   D0 BE       BNE   $025D
029F-   B0 BD       BCS   $025E
02A1-   A0 9A       LDY   #$9A
02A3-   84 3C       STY   $3C
02A5-   BC 8C C0    LDY   $C08C,X
02A8-   10 FB       BPL   $02A5

; Ah, this was the purpose of the table
; we set up earlier: it's a decryption
; table.
02AA-   59 00 08    EOR   $0800,Y
02AD-   A4 3C       LDY   $3C
02AF-   88          DEY
02B0-   99 00 08    STA   $0800,Y
02B3-   D0 EE       BNE   $02A3
02B5-   84 3C       STY   $3C
02B7-   BC 8C C0    LDY   $C08C,X
02BA-   10 FB       BPL   $02B7
02BC-   59 00 08    EOR   $0800,Y
02BF-   A4 3C       LDY   $3C
02C1-   91 26       STA   ($26),Y
02C3-   C8          INY
02C4-   D0 EF       BNE   $02B5
02C6-   BC 8C C0    LDY   $C08C,X
02C9-   10 FB       BPL   $02C6
02CB-   59 00 08    EOR   $0800,Y
02CE-   D0 8D       BNE   $025D
02D0-   60          RTS

Continuing from where we left off...

0237-   A9 A9       LDA   #$A9
0239-   8D 0F 03    STA   $030F
023C-   A9 02       LDA   #$02
023E-   8D 10 03    STA   $0310
0241-   4C 01 03    JMP   $0301

OK, it looks like the decryption is
self-contained, so I'm going to let it
happen, then interrupt the boot before
it jumps to $0301. One thing I'm not
sure of is which bytes in the $0800
page are part of the decryption table.
To be safe, I'm not going to change any
bytes in the $0800..$08FF range. That
will require a little more code on my
part, but not much.

*9600<C600.C6FFM

; replicate the memory move
96F8-   A2 00       LDX   #$00
96FA-   BD 00 08    LDA   $0800,X
96FD-   9D 00 02    STA   $0200,X
9700-   E8          INX
9701-   D0 F7       BNE   $96FA

; now set up a callback to a routine
; under my control
9703-   A9 10       LDA   #$10
9705-   8D 42 02    STA   $0242
9708-   A9 97       LDA   #$97
970A-   8D 43 02    STA   $0243

; start the boot
970D-   4C 0F 02    JMP   $020F

; callback is here -- move the code
; from $0300 to the graphics page so it
; can survive a reboot
9710-   A0 00       LDY   #$00
9712-   B9 00 03    LDA   $0300,Y
9715-   99 00 23    STA   $2300,Y
9718-   C8          INY
9719-   D0 F7       BNE   $9712

; turn off slot 6 drive motor
971B-   AD E8 C0    LDA   $C0E8

; reboot to my work disk
971E-   4C 00 C5    JMP   $C500

*BSAVE TRACE1,A$9600,L$121

*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE BOOT1 0300-03FF,A$2300,L$100
]CALL -151

*300<2300.23FFM

*301L

0301-   78          SEI
0302-   D8          CLD

; I have no idea what this is doing.
0303-   B9 00 08    LDA   $0800,Y
0306-   0A          ASL
0307-   0A          ASL
0308-   0A          ASL
0309-   99 00 08    STA   $0800,Y
030C-   C8          INY
030D-   D0 F4       BNE   $0303

; This is even weirder -- it literally
; does nothing, repeatedly. It's not a
; wait loop. Maybe a simplified version
; of a more complicated boot routine?
030F-   A9 02       LDA   #$02
0311-   A0 1E       LDY   #$1E
0313-   EA          NOP
0314-   EA          NOP
0315-   EA          NOP
0316-   EA          NOP
0317-   EA          NOP
0318-   EA          NOP
0319-   EA          NOP
031A-   EA          NOP
031B-   C8          INY
031C-   D0 F5       BNE   $0313

; write-enable RAM bank 1
031E-   AD 89 C0    LDA   $C089
0321-   AD 89 C0    LDA   $C089

; clear all memory (including RAM bank)
0324-   20 7B 03    JSR   $037B

; write-enable RAM bank 2
0327-   AD 81 C0    LDA   $C081
032A-   AD 81 C0    LDA   $C081

; clear all memory again (including RAM
; bank)
032D-   20 7B 03    JSR   $037B

; now *this* looks like a normal sector
; read loop (much like DOS 3.3 uses in
; its boot0 code)
0330-   A9 09       LDA   #$09
0332-   85 27       STA   $27
0334-   4A          LSR
0335-   85 39       STA   $39
0337-   85 3F       STA   $3F
0339-   84 38       STY   $38
033B-   84 3E       STY   $3E
033D-   AD 0F 03    LDA   $030F
0340-   8D 50 03    STA   $0350
0343-   AD 10 03    LDA   $0310
0346-   8D 51 03    STA   $0351

; set up entry point to disk controller
; ROM routine, based on the slot number
; we booted from (still in zero page
; $2B at this point)
0349-   A6 2B       LDX   $2B
034B-   8A          TXA
034C-   4A          LSR
034D-   4A          LSR
034E-   4A          LSR
034F-   4A          LSR
0350-   09 C0       ORA   #$C0
0352-   85 37       STA   $37
0354-   A9 5D       LDA   #$5D
0356-   85 36       STA   $36
0358-   E6 3D       INC   $3D

; turn on hi-res graphics page
035A-   AD 54 C0    LDA   $C054
035D-   AD 57 C0    LDA   $C057
0360-   AD 52 C0    LDA   $C052
0363-   AD 50 C0    LDA   $C050

; read sector via ($0036), a.k.a. $C65D
0366-   20 78 03    JSR   $0378

; another decryption routine
0369-   20 9E 03    JSR   $039E

; after 4 sectors, break out of read
; loop and continue execution at $039A
036C-   A5 3D       LDA   $3D
036E-   49 03       EOR   #$03
0370-   F0 28       BEQ   $039A
0372-   E6 39       INC   $39
0374-   E6 3D       INC   $3D
0376-   D0 EE       BNE   $0366
...

; execution continues here
039A-   A0 18       LDY   #$18
039C-   D0 62       BNE   $0400

So this is loading 4 sectors into the
text page at $0400..$07FF. I'm guessing
this is the RWTS that will read the
rest of the disk. Whatever it is, I
need to capture it. Luckily, there's
more than enough space at $039A to put
a JMP to a routine under my control.
Unluckily, this code wiped memory
(twice!) before reading the RWTS, so I
will need to disable that before I can
set up a callback.

*9600<C600.C6FFM

; first part is the same as TRACE1 --
; replicate the memory move and set up
; a callback before jumping to $0301
96F8-   A2 00       LDX   #$00
96FA-   BD 00 08    LDA   $0800,X
96FD-   9D 00 02    STA   $0200,X
9700-   E8          INX
9701-   D0 F7       BNE   $96FA
9703-   A9 10       LDA   #$10
9705-   8D 42 02    STA   $0242
9708-   A9 97       LDA   #$97
970A-   8D 43 02    STA   $0243

; start the boot
970D-   4C 0F 02    JMP   $020F

; callback #1 is here --
; disable memory wipe subroutine at
; $037B
9710-   A9 60       LDA   #$60
9712-   8D 7B 03    STA   $037B

; set up callback #2 before branch to
; $0400
9715-   A9 4C       LDA   #$4C
9717-   8D 9A 03    STA   $039A
971A-   A9 27       LDA   #$27
971C-   8D 9B 03    STA   $039B
971F-   A9 97       LDA   #$97
9721-   8D 9C 03    STA   $039C

; continue the boot
9724-   4C 01 03    JMP   $0301

; callback #2 is here --
; copy code from text page to graphics
; page so it can survive a reboot
9727-   A2 06       LDX   #$06
9729-   A0 00       LDY   #$00
972B-   B9 00 04    LDA   $0400,Y
972E-   99 00 24    STA   $2400,Y
9731-   C8          INY
9732-   D0 F7       BNE   $972B
9734-   EE 2D 97    INC   $972D
9737-   EE 30 97    INC   $9730
973A-   CA          DEX
973B-   D0 EE       BNE   $972B

; turn off slot 6 drive motor
973D-   AD E8 C0    LDA   $C0E8

; reboot to my work disk
9740-   4C 00 C5    JMP   $C500

*BSAVE TRACE1B,A$9600,L$143

*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE BOOT1 0400-09FF,A$2400,L$600
]CALL -151

(The code at $0400..$07FF is loaded in
$2400..$27FF, so everything is off by
$2000. Relative branches will look
correct, but absolute addresses will
be off by $2000.)

*2400L

; copy The Badlands to zero page (it
; wipes all of memory and reboots)
2400-   A2 2A       LDX   #$2A
2402-   BD 15 06    LDA   $0615,X
2405-   95 00       STA   $00,X
2407-   CA          DEX
2408-   D0 F8       BNE   $2402

; wipe RAM bank 2 (again!)
240A-   2C 81 C0    BIT   $C081
240D-   2C 81 C0    BIT   $C081
2410-   A2 30       LDX   #$30
2412-   A0 00       LDY   #$00
2414-   A9 D0       LDA   #$D0
2416-   85 2D       STA   $2D
2418-   A9 00       LDA   #$00
241A-   85 2C       STA   $2C
241C-   B1 2C       LDA   ($2C),Y
241E-   91 2C       STA   ($2C),Y
2420-   C8          INY
2421-   D0 F9       BNE   $241C
2423-   E6 2D       INC   $2D
2425-   CA          DEX
2426-   D0 F4       BNE   $241C

; set all possible reset vectors to
; point to The Badlands
2428-   AD 83 C0    LDA   $C083
242B-   AD 83 C0    LDA   $C083
242E-   A9 02       LDA   #$02
2430-   8D F2 03    STA   $03F2
2433-   8D FC FF    STA   $FFFC
2436-   A9 00       LDA   #$00
2438-   8D F3 03    STA   $03F3
243B-   8D FD FF    STA   $FFFD
243E-   49 A5       EOR   #$A5
2440-   8D F4 03    STA   $03F4
2443-   AD 0F 03    LDA   $030F
2446-   85 47       STA   $47

; show graphics page (again!)
2448-   2C 50 C0    BIT   $C050
244B-   2C 52 C0    BIT   $C052
244E-   2C 54 C0    BIT   $C054
2451-   2C 57 C0    BIT   $C057

; wipe memory (again!)
2454-   A2 20       LDX   #$20
2456-   A0 00       LDY   #$00
2458-   A9 AA       LDA   #$AA
245A-   48          PHA
245B-   A5 47       LDA   $47
245D-   C9 A9       CMP   #$A9
245F-   D0 04       BNE   $2465
2461-   68          PLA
2462-   A9 2A       LDA   #$2A
2464-   48          PHA
2465-   68          PLA
2466-   84 37       STY   $37
2468-   86 38       STX   $38
246A-   91 37       STA   ($37),Y
246C-   C8          INY
246D-   D0 FB       BNE   $246A
246F-   E6 38       INC   $38
2471-   CA          DEX
2472-   D0 F6       BNE   $246A
2474-   4C 8D 05    JMP   $058D

*258DL

; this is a read loop
258D-   A9 00       LDA   #$00
258F-   85 35       STA   $35
2591-   85 42       STA   $42
2593-   85 40       STA   $40
2595-   A9 04       LDA   #$04
2597-   85 30       STA   $30

; zero page $44 holds the target page
; (first load is at $0A00)
2599-   A9 0A       LDA   #$0A
259B-   85 44       STA   $44
259D-   E6 42       INC   $42
259F-   A9 04       LDA   #$04
25A1-   85 30       STA   $30
25A3-   A5 42       LDA   $42
25A5-   A6 2B       LDX   $2B
25A7-   20 EB 04    JSR   $04EB
25AA-   A5 44       LDA   $44
25AC-   85 36       STA   $36
25AE-   A6 2B       LDX   $2B
25B0-   20 79 04    JSR   $0479

; if read fails, jump to The Badlands
25B3-   B0 48       BCS   $25FD
25B5-   18          CLC

; apparently only 8 sectors worth of
; data on each track
25B6-   A9 08       LDA   #$08
25B8-   65 44       ADC   $44
25BA-   85 44       STA   $44
25BC-   C9 9A       CMP   #$9A
25BE-   90 DD       BCC   $259D

; turn off drive motor
25C0-   BD 88 C0    LDA   $C088,X
25C3-   A9 FE       LDA   #$FE
25C5-   8D 00 02    STA   $0200
25C8-   A9 00       LDA   #$00
25CA-   85 B1       STA   $B1
25CC-   A9 AA       LDA   #$AA
25CE-   85 36       STA   $36
25D0-   A9 81       LDA   #$81
25D2-   85 FD       STA   $FD
25D4-   A2 30       LDX   #$30
25D6-   BD 08 06    LDA   $0608,X
25D9-   9D 05 93    STA   $9305,X
25DC-   CA          DEX
25DD-   D0 F7       BNE   $25D6

; read/write RAM bank 2
25DF-   AD 83 C0    LDA   $C083
25E2-   AD 83 C0    LDA   $C083

; set reset vector (again!)
25E5-   A9 93       LDA   #$93
25E7-   8D FD FF    STA   $FFFD
25EA-   8D F3 03    STA   $03F3
25ED-   A9 00       LDA   #$00
25EF-   8D FC FF    STA   $FFFC
25F2-   8D F2 03    STA   $03F2
25F5-   A9 36       LDA   #$36
25F7-   8D F4 03    STA   $03F4

; jump to program start
25FA-   4C 00 60    JMP   $6000

; only tolerate a certain number of
; read failures before jumping to The
; Badlands memory wipe routine on the
; zero page
25FD-   C6 30       DEC   $30
25FF-   D0 A2       BNE   $25A3
2601-   BD 88 C0    LDA   $C088,X
2604-   4C 02 00    JMP   $0002

The game is loaded in one contiguous
block in main memory. If I interrupt
the boot at $05FA (the instruction that
jumps to the start of the game), I can
get full access to the entire code,
save it off in pieces to my work disk,
and combine it into a single binary
file later.

*9600<C600.C6FFM

; replicate the memory move and set up
; a callback before jumping to $0301
96F8-   A2 00       LDX   #$00
96FA-   BD 00 08    LDA   $0800,X
96FD-   9D 00 02    STA   $0200,X
9700-   E8          INX
9701-   D0 F7       BNE   $96FA
9703-   A9 10       LDA   #$10
9705-   8D 42 02    STA   $0242
9708-   A9 97       LDA   #$97
970A-   8D 43 02    STA   $0243
970D-   4C 0F 02    JMP   $020F

; callback #1 is here -- defeat memory
; wipe and set up second callback once
; RWTS is loaded into text page
9710-   A9 60       LDA   #$60
9712-   8D 7B 03    STA   $037B
9715-   A9 4C       LDA   #$4C
9717-   8D 9A 03    STA   $039A
971A-   A9 27       LDA   #$27
971C-   8D 9B 03    STA   $039B
971F-   A9 97       LDA   #$97
9721-   8D 9C 03    STA   $039C

; continue the boot
9724-   4C 01 03    JMP   $0301

; callback #2 is here -- jump to
; monitor instead of starting game
9727-   A9 59       LDA   #$59
9729-   8D FB 05    STA   $05FB
972C-   A9 FF       LDA   #$FF
972E-   8D FC 05    STA   $05FC

; continue the boot
9731-   4C 00 04    JMP   $0400

*BSAVE TRACE1C,A$9600,L$134

*9600G
...reboots slot 6...
<beep>

A few manual memory moves and reboots
later, I have the entire game in three
segments:

 B 026 RIBBIT 0800-1FFF
 B 066 RIBBIT 2000-5FFF
 B 060 RIBBIT 6000-99FF

]BLOAD RIBBIT 0800-1FFF,A$800
]BLOAD RIBBIT 2000-5FFF,A$2000
]BLOAD RIBBIT 6000-99FF,A$6000
]CALL -151

*7FD:4C 00 60

*BSAVE RIBBIT (4AM CRACK),A$7FD,L$9203

In an attempt to more faithfully
reproduce the experience of booting the
original disk, I've put this binary
file on its own disk with a modified
CompatiBoot loader. Like the original
disk, my loader switches to the hi-res
graphics page immediately on boot, so
you can see the title screen load over
the (uninitialized) graphics page. But
you can run the binary file from any
DOS 3.3 compatible disk. (You may need
"MAXFILES 1" first, since it extends
beyond the $9600 boundary that DOS uses
for file buffers.)

Quod erat liberandum.

---------------------------------------
A 4am crack                      No. 73
------------------EOF------------------