💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › action › Ribbit%20(4am%2… captured on 2024-05-26 at 17:31:47.
⬅️ 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------------------