💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › simulation › Dive%20Bomb… captured on 2024-08-18 at 17:56:39.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

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

--------------Dive Bomber--------------
A 4am crack                  2015-03-02
---------------------------------------

Name: Dive Bomber
Genre: games/simulation
Year: 1988
Authors: Acme Animation, Inc.
Publisher: Epyx
Media: single-sided 5.25-inch floppy
OS: custom
Other versions: DataWiz / 6502 Crew

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate disk read error

Locksmith Fast Disk Backup
  unable to read any track

EDD 4 bit copy (no sync, no count)
  no errors, but copy just reboots

Copy ][+ nibble editor
  modified address and data epilogues
    (FF FF EB)
  
Disk Fixer
  ["O" -> "Input/Output Control"]
    set Address Epilogue to "AA DE EB"
    set Data Epilogue to "AA DE EB"
  all tracks readable
  T00,S00 -> custom boot that relocates
    to $0200
  no evidence of disk catalog anywhere
  no evidence of any standard OS

Why didn't COPYA work?
  modified epilogue bytes

Why didn't Locksmith FDB work?
  ditto

Why didn't my EDD copy work?
  probably a nibble check during boot

Next steps:

  1. use Super Demuffin to convert disk
     to standard format
  2. patch RWTS to read standard format
     (if necessary)
  3. find nibble check and bypass it

                   ~

               Chapter 1
     In Which Our Adventure Begins
But We Encounter Ominous Foreshadowing
          Almost Immediately


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

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

I'll look at that later. First I want
to use Super Demuffin to convert the
disk to a standard format.

]BRUN SUPER DEMUFFIN

                 --v--

      SUPER-DEMUFFIN AND FAST COPY
Modified by: The Saltine/Coast to Coast


   Address prologue: D5 AA 96

   Address epilogue: FF FF EB    DISK
                     ^^^^^     ORIGINAL
   was "DE AA"-------+++++

      Data prologue: D5 AA AD

      Data epilogue: FF FF EB
                     ^^^^^
   was "DE AA"-------+++++


 Ignore write errors while demuffining!


  D - Edit parameters
      <SPACE> - Advance to next parm
      <RETURN> - Exit edit mode
  R - Restore DOS 3.3 parameters
  O - Edit Original disk's parameters
  C - Edit Copy disk's parameters
  G - Begin demuffin process

                 --^--

Pressing "G" switches to the Locksmith
Fast Disk Copy UI.

                 --v--

     LOCKSMITH 7.0  FAST DISK BACKUP


   R...................................
   W***********************************
HEX 00000000000000001111111111111111222
TRK 0123456789ABCDEF0123456789ABCDEF012
   0...................................
   1...................................
   2...................................
   3...................................
   4...................................
   5...................................
   6...................................
   7...................................
   8...................................
   9...................................
   A...................................
   B...................................
   C...................................
   D...................................
12 E...................................
   F..................................D
[               ] PRESS [RESET] TO EXIT

                 --^--

Hmm, can't read T22,S0F. The original
disk has no problems booting, so I'm
guessing that's part of the copy
protection.

[S6,D1=Super Demuffin'd copy]

]PR#6
...swings to high track then hangs...

Let's go find that nibble check.

                   ~

               Chapter 2
      In Which We Twist And Turn,
      And Things Get Interesting


]PR#5
]BLOAD BOOT0,A$800
]CALL -151



0801-   D8          CLD
0802-   78          SEI

; copy boot0 to $0200, but don't jump
; to it
0803-   A0 00       LDY   #$00
0805-   B9 00 08    LDA   $0800,Y
0808-   99 00 02    STA   $0200,Y
080B-   C8          INY
080C-   D0 F7       BNE   $0805

; store slot number (x16)
080E-   8E 71 02    STX   $0271
0811-   8E 7F 02    STX   $027F

; set input and output vectors
0814-   A9 FD       LDA   #$FD
0816-   85 37       STA   $37
0818-   85 39       STA   $39
081A-   A9 F0       LDA   #$F0
081C-   85 36       STA   $36
081E-   A9 1B       LDA   #$1B
0820-   85 38       STA   $38

; self-modifying code alert!
; change $0801 to "JMP $0247"
0822-   A9 4C       LDA   #$4C
0824-   8D 01 08    STA   $0801
0827-   A9 47       LDA   #$47
0829-   8D 02 08    STA   $0802
082C-   A9 02       LDA   #$02
082E-   8D 03 08    STA   $0803

; set up ($3E) to point inside disk
; controller ROM routine so we can
; read sectors
0831-   8A          TXA
0832-   4A          LSR
0833-   4A          LSR
0834-   4A          LSR
0835-   4A          LSR
0836-   09 C0       ORA   #$C0
0838-   85 3F       STA   $3F
083A-   A9 5C       LDA   #$5C
083C-   85 3E       STA   $3E

; switch to language card RAM bank 2
083E-   2C 81 C0    BIT   $C081
0841-   2C 81 C0    BIT   $C081
0844-   2C 83 C0    BIT   $C083

; call a subroutine that used to be at
; $0896 but was copied to low memory
0847-   20 96 02    JSR   $0296



0296-   CE 7B 02    DEC   $027B
0299-   30 FA       BMI   $0295 ; ->RTS
029B-   CE 79 02    DEC   $0279
029E-   AD 79 02    LDA   $0279
02A1-   85 27       STA   $27
02A3-   CE 75 02    DEC   $0275
02A6-   AC 75 02    LDY   $0275
02A9-   B9 B4 02    LDA   $02B4,Y
02AC-   85 3D       STA   $3D
02AE-   AE 71 02    LDX   $0271
02B1-   6C 3E 00    JMP   ($003E)

This is weird, but not the weirdest
thing I've ever seen on T00,S00. The
disk controller ROM routine will read a
sector and jump to $0801. Since $0801
now jumps to $0247, which calls this
routine, this is a multi-sector read
loop. It terminates when $027B goes
negative and $0299 branches to $0295
(which is an RTS). The stack unwinds
and execution continues at $084A after
the initial JSR.

$027B - sector count (starts at $08)
$0279 - page (start at $00, but it's
        decremented before first read,
        so this reads 8 sectors into
        $F800..$FFFF)
$0275 - logical sector (starts at $09,
        but it's decremented before
        the first read, so sectors
        $01 through $08 contain the
        code loaded into $F800..$FFFF)

; more self-modifying code --
; now $0801 jumps to $025E
084A-   A9 5E       LDA   #$5E
084C-   8D 02 08    STA   $0802

; change the parameters used by the
; multi-sector read loop so we're
; reading 7 sectors into $5F00..$66FF
084F-   A9 07       LDA   #$07
0851-   8D 7B 02    STA   $027B
0854-   A9 66       LDA   #$66
0856-   8D 79 02    STA   $0279
0859-   A9 10       LDA   #$10
085B-   8D 75 02    STA   $0275

; call multi-sector read routine, which
; returns here (because of new jump at
; $0801) and eventually continues after
; this instruction
085E-   20 96 02    JSR   $0296

; smash low-level reset vector (defense
; against copy cards)
0861-   A0 05       LDY   #$05
0863-   B9 FA FF    LDA   $FFFA,Y
0866-   99 FA FF    STA   $FFFA,Y
0869-   88          DEY
086A-   10 F7       BPL   $0863
086C-   78          SEI

; jump to next stage of the boot
086D-   4C 00 5F    JMP   $5F00

                   ~

               Chapter 3
  In Which We Bump Into An Old Friend
   Who Has Grown Mean And Crotchety


I need to capture the code at $5F00
(called from $086D).



; set up callback instead of jumping
; to $5F00
96F8-   48          PHA
96F9-   A9 4C       LDA   #$4C
96FB-   8D 61 08    STA   $0861
96FE-   A9 0C       LDA   #$0C
9700-   8D 62 08    STA   $0862
9703-   A9 97       LDA   #$97
9705-   8D 63 08    STA   $0863
9708-   68          PLA

; start the boot
9709-   4C 01 08    JMP   $0801

; callback is here -- switch from RAM
; bank 2 to ROM and break to monitor
970C-   AD 82 C0    LDA   $C082
970F-   4C 59 FF    JMP   $FF59


...reboots slot 6...
<beep>

...
]BSAVE BOOT1 5F00-65FF,A$5F00,L$700
]CALL -151


5F00-   A9 00       LDA   #$00
5F02-   8D DF FF    STA   $FFDF

; probably positioning the drive head
; to track $22
5F05-   A9 44       LDA   #$44
5F07-   A6 2B       LDX   $2B
5F09-   20 A3 FB    JSR   $FBA3

; initialize death counter
5F0C-   A9 0A       LDA   #$0A
5F0E-   85 FC       STA   $FC

; turn on drive motor manually
5F10-   A6 2B       LDX   $2B
5F12-   BD 89 C0    LDA   $C089,X
5F15-   BD 8E C0    LDA   $C08E,X

; secondary death counter
5F18-   A9 80       LDA   #$80
5F1A-   85 FD       STA   $FD
5F1C-   C6 FD       DEC   $FD

; if this hits 0, nibble check fails
5F1E-   F0 71       BEQ   $5F91

; subroutine looks for next available
; address field
5F20-   20 AF 5F    JSR   $5FAF

; can't find one --> fail immediately
5F23-   B0 6C       BCS   $5F91

; check if it's sector $0F
5F25-   A5 F9       LDA   $F9
5F27-   C9 0F       CMP   #$0F

; loop until it is
5F29-   D0 F1       BNE   $5F1C

Hey, now we're positioned on T22,S0F --
the one sector that I couldn't read.
What a coincidence! (*)

(*) not guaranteed, actual coincidence
    may vary
    
5F2B-   A0 00       LDY   #$00
5F2D-   BD 8C C0    LDA   $C08C,X
5F30-   10 FB       BPL   $5F2D
5F32-   88          DEY
5F33-   F0 5C       BEQ   $5F91
5F35-   C9 D5       CMP   #$D5
5F37-   D0 F4       BNE   $5F2D

; Search for a specific sequence of
; nibbles in the "dead zone" between
; the address field and data field.
; This area is normally not important,
; so Super Demuffin didn't copy it
; precisely because normal disks don't
; care. (Actually, it's even more evil
; than that, because the original disk
; is written with timing bits in
; specific non-standard places between
; the nibbles in the dead zone. This
; code not only requires the right
; nibbles in the right order, it reads
; them slightly slower than normal. So
; the timing bits need to be in the
; right places too, or else this code
; will read the wrong nibble values
; while it's out of sync. This will
; trip up even the best bit copiers.
; And you can forget about making a
; disk image for emulators -- those
; don't store timing bits at all.)
5F39-   A0 00       LDY   #$00
5F3B-   BD 8C C0    LDA   $C08C,X
5F3E-   10 FB       BPL   $5F3B
5F40-   88          DEY
5F41-   F0 4E       BEQ   $5F91  ; fail
5F43-   C9 E7       CMP   #$E7
5F45-   D0 F4       BNE   $5F3B
5F47-   BD 8C C0    LDA   $C08C,X
5F4A-   10 FB       BPL   $5F47
5F4C-   C9 E7       CMP   #$E7
5F4E-   D0 41       BNE   $5F91  ; fail
5F50-   BD 8C C0    LDA   $C08C,X
5F53-   10 FB       BPL   $5F50
5F55-   C9 E7       CMP   #$E7
5F57-   D0 38       BNE   $5F91  ; fail

; kill some time to get out of sync
; with the "proper" start of nibbles)
5F59-   BD 8D C0    LDA   $C08D,X
5F5C-   A0 10       LDY   #$10
5F5E-   24 80       BIT   $80

; now start looking for nibbles that
; don't really exist (except they do,
; because we're out of sync and reading
; timing bits as data)
5F60-   BD 8C C0    LDA   $C08C,X
5F63-   10 FB       BPL   $5F60
5F65-   88          DEY
5F66-   F0 29       BEQ   $5F91
5F68-   C9 EE       CMP   #$EE
5F6A-   D0 F4       BNE   $5F60
5F6C-   EA          NOP
5F6D-   EA          NOP

; store next 8 nibbles in zero page
5F6E-   A0 F8       LDY   #$F8
5F70-   BD 8C C0    LDA   $C08C,X
5F73-   10 FB       BPL   $5F70
5F75-   99 00 00    STA   $0000,Y
5F78-   EA          NOP
5F79-   C8          INY
5F7A-   30 F4       BMI   $5F70
5F7C-   A9 00       LDA   #$00
5F7E-   A8          TAY
5F7F-   85 F0       STA   $F0
5F81-   A2 02       LDX   #$02
5F83-   A9 F8       LDA   #$F8
5F85-   20 9E 5F    JSR   $5F9E



; decrypt part of the RWTS based on the
; magic nibble sequence
5F9E-   85 F1       STA   $F1
5FA0-   B5 F8       LDA   $F8,X
5FA2-   51 F0       EOR   ($F0),Y
5FA4-   91 F0       STA   ($F0),Y
5FA6-   88          DEY
5FA7-   D0 F7       BNE   $5FA0
5FA9-   E6 F1       INC   $F1
5FAB-   CA          DEX
5FAC-   10 F2       BPL   $5FA0
5FAE-   60          RTS

This is particularly evil, because it
means I can't just bypass this nibble
check. Part of the RWTS ($F800..$F9FF)
is encrypted on disk, and the key to
decrypt it is out-of-phase in the
unreadable T22,S0F.



; move drive head back to track $00
5F88-   A6 2B       LDX   $2B
5F8A-   98          TYA
5F8B-   20 A3 FB    JSR   $FBA3

; continue with real boot1 code (now
; decrypted)
5F8E-   4C 00 F8    JMP   $F800

; The Badlands -- decrement death
; counters and eventually reboot
5F91-   C6 FC       DEC   $FC
5F93-   F0 03       BEQ   $5F98
5F95-   4C 18 5F    JMP   $5F18
5F98-   EE F4 03    INC   $03F4
5F9B-   6C FC FF    JMP   ($FFFC)

I'm going to need to trace past this
nibble check, then interrupt it before
it jumps to the (decrypted) $F800 to
load the game.

                   ~

               Chapter 4
   In Which We Decide We Don't Need
    Friends Like That Anyway, So We
      Steal His Key And Run Away,
             I Don't Know,
        This Analogy Got Weird




; set up first callback before calling
; nibble check at $5F00
96F8-   A9 4C       LDA   #$4C
96FA-   8D 61 08    STA   $0861
96FD-   A9 0A       LDA   #$0A
96FF-   8D 62 08    STA   $0862
9702-   A9 97       LDA   #$97
9704-   8D 63 08    STA   $0863

; start the boot
9707-   4C 01 08    JMP   $0801

; first callback is here -- set up
; second callback after RWTS is
; decrypted
970A-   A9 4C       LDA   #$4C
970C-   8D 8E 5F    STA   $5F8E
970F-   A9 1C       LDA   #$1C
9711-   8D 8F 5F    STA   $5F8F
9714-   A9 97       LDA   #$97
9716-   8D 90 5F    STA   $5F90

; execute nibble check
9719-   4C 00 5F    JMP   $5F00

; second callback is here -- RAM bank 2
; contains decrypted RWTS
; read from RAM bank 2 (no write)
971C-   AD 84 C0    LDA   $C084

; copy decrypted RWTS to main memory
; for easy retrieval
971F-   A2 08       LDX   #$08
9721-   A0 00       LDY   #$00
9723-   B9 00 F8    LDA   $F800,Y
9726-   99 00 28    STA   $2800,Y
9729-   C8          INY
972A-   D0 F7       BNE   $9723
972C-   EE 25 97    INC   $9725
972F-   EE 28 97    INC   $9728
9732-   CA          DEX
9733-   D0 EE       BNE   $9723

; read and write from ROM
9735-   AD 82 C0    LDA   $C082

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

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


...reboots slot 6...
...reboots slot 5...
]BSAVE BOOT1 F800-FFFF DECRYPTED,
 A$2800,L$800

Now to write the decrypted RWTS to
track 0, sectors 1-8.

]CALL -151

; just a straightforward multi-sector
; write loop, via the RWTS vector at
; $03D9
08C0-   A9 08       LDA   #$08
08C2-   A0 E8       LDY   #$E8
08C4-   20 D9 03    JSR   $03D9
08C7-   AC ED 08    LDY   $08ED
08CA-   88          DEY
08CB-   10 05       BPL   $08D2
08CD-   A0 0F       LDY   #$0F
08CF-   CE EC 08    DEC   $08EC
08D2-   8C ED 08    STY   $08ED
08D5-   CE F1 08    DEC   $08F1
08D8-   CE E1 08    DEC   $08E1
08DB-   D0 E3       BNE   $08C0
08DD-   60          RTS

         +-- sector count
         v
08E0- 00 08 00 00 00 00 00 00

08E8- 01 60 01 00 00 08 FB 08
                  ^   ^
          track --+   +-- sector

08F0- 00 2F 00 00 02 00 FE 60
          ^
          +-- starting address

08F8- 01 00 00 00 01 EF D8 00


 A$8C0,L$40



And finally, skip the nibble check and
jump straight to the actual boot1 code
at $F800:

T00,S00,$6F change "5F" to "F8"

It turns out the RWTS is permissive
enough to read the copy, even though
it uses standard epilogue bytes. So no
further patches are required.

Quod erat liberandum.

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