💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › action › hero › H.E.R.O.… captured on 2024-08-19 at 03:42:02.

View Raw

More Information

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

----------------H.E.R.O.---------------
A 4am crack                  2015-11-18
---------------------------------------

Name: H.E.R.O.: Helicopter Emergency
  Rescue Operation
Genre: arcade
Year: 1984
Credits:
  Designed by John Van Ryzin
  Adapted by Charlie Heath, Microsmiths
Publisher: Activision, Inc.
Media: single-sided 5.25-inch floppy
OS: custom with DOS 3.3 bootloader
Previous cracks: The Syndicate

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate disk read error

Locksmith Fast Disk Backup
  able to read a few sectors from track
  $00 (specifically, 0, 4, 5, 6, 7, 8,
  9, A, B, and F) but nothing else

EDD 4 bit copy (no sync, no count)
  no errors, but copy grinds endlessly

Copy ][+ nibble editor
  modified prologues and epilogues on
  track 1+ (and those unreadable
  sectors on track 0)
  address = AA D5 AB / DE AB *
  data    = AA D5 EB / ED AA EB

                 --v--

   COPY ][ PLUS BIT COPY PROGRAM 8.4
(C) 1982-9 CENTRAL POINT SOFTWARE, INC.
---------------------------------------

TRACK: 03  START: 2E71  LENGTH: 015F

2E60: 96 96 96 96 FD FA AB B7   VIEW
2E68: F3 E5 ED AA EB FF FF FF
            ^^^^^^^^
         data epilogue

2E70: FF FD CA F3 B4 FF DB B7
2E78: AD BF D7 AB F7 AA D5 AB
                     ^^^^^^^^
                  address prologue

2E80: FF FE AB AB AF AF FB FA  <-2E81
      ^^^^^ ^^^^^ ^^^^^ ^^^^^
      v=255 t=$03 s=$0F chksm

2E88: DE AB E9 FF D3 EE BD EB
      ^^^^^
 address epilogue

2E90: AF ED FF DB B7 AA D5 EB
                     ^^^^^^^^
                   data prologue

2E98: F9 DD DB 9E EF 9D BD CF
2EA0: F4 B6 AD 9A 9E D7 E9 EA

---------------------------------------

  A  TO ANALYZE DATA  ESC TO QUIT

  ?  FOR HELP SCREEN  /  CHANGE PARMS

  Q  FOR NEXT TRACK   SPACE TO RE-READ

                 --^--

Disk Fixer
  ["O" -> "Input/Output Control"]
    set Address Prologue to "AA D5 AB"
    set Address Epilogue to "DE AB EB"
    set Data Prologue to "AA D5 EB"
    set Data Epilogue to "ED AA EB"
    Success! T01-T07 readable!
    T11 has a standard DOS 3.3 disk
      catalog with a small HELLO in
      BASIC (probably a ruse)
    all other tracks (T08-T10, T13+)
      are formatted but blank

Why didn't COPYA work?
  modified prologues/epilogues

Why didn't Locksmith FDB work?
  modified prologues/epilogues

Why didn't my EDD copy work?
  I don't know. Disk grinding usually
  points to a structural protection,
  but I was able to read the disk with
  a sector editor once I modified the
  prologues and epilogues. So maybe a
  runtime protection check that tries
  endlessly?

Next steps:

  1. capture RWTS with AUTOTRACE
  2. convert disk to standard format
     with Advanced Demuffin
  3. patch RWTS to read standard format

                   ~

               Chapter 1
In Which We Attempt To Use The Original
    Disk As A Weapon Against Itself
      But Get Distracted When We
        Stop And Smell The RWTS


[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
CAPTURING BOOT1
...reboots slot 6...
...reboots slot 5...
SAVING BOOT1

Hmm, my AUTOTRACE scripts captured the
boot1 but didn't think it contained a
DOS 3.3-shaped RWTS. That usually means
something... interesting... is afoot.

]BLOAD BOOT1,A$2600
]CALL -151

; copy most of boot1 except the last
; page (Diversi-DOS 64K uses $BFxx)


; stashing the boot slot (x16)
B700-   8E 34 B7    STX   $B734
B703-   8E 42 B7    STX   $B742

; overwriting the entire RWTS parameter
; table
B706-   A0 10       LDY   #$10
B708-   B9 33 B7    LDA   $B733,Y
B70B-   99 E8 B7    STA   $B7E8,Y
B70E-   88          DEY
B70F-   10 F7       BPL   $B708
B711-   A0 03       LDY   #$03
B713-   B9 44 B7    LDA   $B744,Y
B716-   99 FB B7    STA   $B7FB,Y
B719-   88          DEY
B71A-   10 F7       BPL   $B713

; call the RWTS to read a sector
B71C-   A9 B7       LDA   #$B7
B71E-   A0 E8       LDY   #$E8
B720-   20 B5 B7    JSR   $B7B5

; and again, with the next sector
B723-   EE F1 B7    INC   $B7F1
B726-   EE ED B7    INC   $B7ED
B729-   A9 B7       LDA   #$B7
B72B-   A0 E8       LDY   #$E8
B72D-   20 B5 B7    JSR   $B7B5
B72D-   20 B5 B7    JSR   $B7B5

; and jump there (presumably)
B730-   4C 00 90    JMP   $9000

Several things to note here: it appears
to be using the standard DOS 3.3 RWTS
entry point at $B7B5. (Not shown, but
that routine is also standard, calling
the entry point at $BD00.)

But digging a little further into the
RWTS itself... now that's where it gets
interesting. A lot of code has been
moved around (which explains why my
automated scripts didn't think there
was an RWTS in here). For example, here
is the code to read the data field,
starting with the (modified) prologue:



; get first nibble of data prologue
B9CD-   BD 8C C0    LDA   $C08C,X
B9D0-   10 FB       BPL   $B9CD

; subroutine is just an RTS (but it
; takes 12 cycles to call and return)
B9D2-   20 59 BA    JSR   $BA59

; $AA is OK
B9D5-   C9 AA       CMP   #$AA
B9D7-   F0 04       BEQ   $B9DD

; but $D5 is also OK
B9D9-   C9 D5       CMP   #$D5
B9DB-   D0 EA       BNE   $B9C7
B9DD-   EA          NOP

; get second nibble of data prologue
B9DE-   BD 8C C0    LDA   $C08C,X
B9E1-   10 FB       BPL   $B9DE

; $D5 is OK
B9E3-   C9 D5       CMP   #$D5
B9E5-   F0 04       BEQ   $B9EB

; but so is $AA
B9E7-   C9 AA       CMP   #$AA
B9E9-   D0 EA       BNE   $B9D5
B9EB-   A0 56       LDY   #$56

; third nibble
B9ED-   BD 8C C0    LDA   $C08C,X
B9F0-   10 FB       BPL   $B9ED

; $EB is OK
B9F2-   C9 EB       CMP   #$EB
B9F4-   F0 04       BEQ   $B9FA

; and so is $AD
B9F6-   C9 AD       CMP   #$AD
B9F8-   D0 DB       BNE   $B9D5

Weird. So this RWTS will accept the
modified data prologue ("AA D5 EB"),
but it will also accept the standard
data prologue ("D5 AA AD"). I've seen
this sort of "double RWTS" in other
programs that need to write to user-
formatted data disks, but as far as I
know, this game is strictly read-only.

But wait, it gets better. After the
standard denibblizing routine, this is
the code to find the data epilogue:



; get first nibble of data epilogue
BA2A-   BD 8C C0    LDA   $C08C,X
BA2D-   10 FB       BPL   $BA2A

; $DE is OK
BA2F-   C9 DE       CMP   #$DE
BA31-   F0 1C       BEQ   $BA4F

; $ED is also OK
BA33-   C9 ED       CMP   #$ED
BA35-   D0 21       BNE   $BA58

; but if we find an $ED, we kill even
; more time (cycle counts in margin)
BA37-   20 59 BA    JSR   $BA59    | 12
BA3A-   EA          NOP            |  2
BA3B-   EA          NOP            |  2
BA3C-   EA          NOP            |  2

; now look at the data latch one more
; time
BA3D-   BD 8C C0    LDA   $C08C,X

; because we killed so much time
; already, this branch will only be
; taken if there was NOT an extra
; "timing bit" after the $ED nibble
BA40-   30 16       BMI   $BA58

; found a timing bit, continue
BA42-   EA          NOP
BA43-   BD 8C C0    LDA   $C08C,X
BA46-   10 FB       BPL   $BA43
BA48-   C9 AA       CMP   #$AA
BA4A-   D0 0C       BNE   $BA58
BA4C-   4C 5A BA    JMP   $BA5A
BA4F-   BD 8C C0    LDA   $C08C,X
BA52-   10 FB       BPL   $BA4F
BA54-   C9 AA       CMP   #$AA
BA56-   F0 02       BEQ   $BA5A

; failure ends up here (from $BA35 if
; we didn't find the first nibble of
; the epilogue, from $BA35 if we didn't
; find the second nibble, or from $BA4A
; if we didn't find the extra timing
; bit after the second nibble)
BA58-   38          SEC
BA59-   60          RTS

; success ends up here (from $BA4C or
; $BA56)
BA5A-   18          CLC
BA5B-   60          RTS

This explains why my EDD bit copy would
just grind forever. The copy doesn't
have those extra timing bits in the
right places (after the second epilogue
nibble after each data field), so the
comparison at $BA40 fails and jumps to
$BA58, which sets the carry flag to
tell the caller that it couldn't read
the sector. The RWTS thinks every
sector on the disk is bad. Which, in a
sense, is true -- it's "bad" because
it's not an original.

There's no separate runtime protection
check. The test of originality is baked
into the RWTS itself.

                   ~

               Chapter 2
        In Which We Get On With
         The Business At Hand


On the bright side, this RWTS is enough
like DOS 3.3 that I should be able to
feed it directly into Advanced Demuffin
and be able to read the original disk.



["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B6, load "BOOT1" from drive 1

["6" to switch to slot 6]

["C" to convert disk]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:...................................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...................................
SC1:...................................
SC2:...................................
SC3:...................................
SC4:...................................
SC5:...................................
SC6:...................................
SC7:...................................
SC8:...................................
SC9:...................................
SCA:...................................
SCB:...................................
SCC:...................................
SCD:...................................
SCE:...................................
SCF:...................................
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

[S6,D1=demuffin'd copy]

]PR#6
...crashes at $BF02...

Wait, what?

Poking around in the monitor (since,
you know, I just crashed into it), I
discover something odd: boot1 is being
loaded, but it's being loaded in all
the wrong places. $BD00 looks correct,
but what is this?



B700-   8C C0 10    STY   $10C0
B703-   FB          ???
B704-   59 00 BC    EOR   $BC00,Y
B707-   A4 26       LDY   $26
B709-   99 00 BC    STA   $BC00,Y
B70C-   D0 EE       BNE   $B6FC
B70E-   84 26       STY   $26

That is not the bootloader code I saw
after I captured the boot sequence from
my work disk. (Cross-checking with the
"BOOT1" file I captured, that code
belongs at $BA00.)

Other pages are similarly out of place.
This can only mean one thing: the
the sector order is wrong.

                   ~

               Chapter 3
In Which The Original Disk Strikes Back


[S6,D1=demuffin'd copy]
[S5,D1=my work disk]

]PR#6
...crashes...

Turning to my trusty Disk Fixer sector
editor, I see that the sectors on T00
are no longer in a "weird order" like
the original disk. T00,S01 is custom,
but it appears to be loaded at $B700.
T00,S02-S09 are the RWTS. This is just
like a DOS 3.3 disk and quite unlike
the original disk.

Suddenly it clicks: this disk's logical
sectors are mapped in a different order
than usual.

Here's T00,S00, split for clarity:

                 --v--

-------------- DISK EDIT --------------
TRACK $00/SECTOR $00/VOLUME $FE/BYTE$00
---------------------------------------
$00:>01<A5 27 C9 09 D0 18 A5   A%'IIPX%
$08: 2B 4A 4A 4A 4A 09 C0 85   +JJJJI@.
$10: 3F A9 5C 85 3E 18 AD FE   ?)\.>X-~
$18: 08 6D FF 08 8D FE 08 AE   H-.H.~H.
$20: FF 08 30 15 BD 4D 08 85   .H0U=MH.
$28: 3D CE FF 08 AD FE 08 85   =N.H-~H.
$30: 27 CE FE 08 A6 2B 6C 3E   'N~H&+,>
$38: 00 EE FE 08 EE FE 08 20   @n~Hn~H
$40: 89 FE 20 93 FE 20 2F FB   .~ .~ /{
$48: A6 2B 6C FD 08            &+,}H

                 --^--

The first $4C bytes are standard. In
fact, they are byte-for-byte identical
to DOS 3.3.

But look at the table that starts at
$084D:

                 --v--

$48:                00 07 0E        @GN
$50: 05 0C 03 0A 01 08 0F 06   ELCJAHOF
$58: 0D 04 0B 02 09            MDKBI

                 --^--

This is the table that the boot0 code
uses to map the logical sector it wants
(loaded into the X register from $08FF)
to the physical sector that is stored
on disk (stored in zero page $3D and
referenced by the disk controller ROM
routine).

Here's the same table from a standard
DOS 3.3 disk:

                 --v--

$48:                00 0D 0B        @MK
$50: 09 07 05 03 01 0E 0C 0A   IGECANLJ
$58: 08 06 04 02 0F            HFDBO

                 --^--

Technically this copy of the sector
table is only used by boot0. The RWTS
has its own copy; usually it starts at
$BFB8, but on this disk it appears to
start at $BFA2. Sure enough, that table
is in the same non-standard order.

Now think about how Advanced Demuffin
works. It uses the original disk's RWTS
to read one sector at a time. "Hey," it
says, "let's read track $0, sector $F."
"Sure thing," replies the RWTS, and it
proceeds to do exactly that. Then,
using a completely separate RWTS (built
into Advanced Demuffin, starting at
$1500), it says "hey, let's write these
256 bytes of data to track $0, sector
$F on a regular disk."

In other words, Advanced Demuffin
normalized the sector order for me in
the processing of converting the disk
to a standard format, but it didn't
patch the RWTS or the boot0 code
(because it never does that).

T00,S00,$4D
  change 00 07 0E 05 0C 03 0A 01
         08 0F 06 0D 04 0B 02 09
      to 00 0D 0B 09 07 05 03 01
         0E 0C 0A 08 06 04 02 0F

And also the copy that the RWTS itself
uses, which is at $BFA2:

T00,S09,$A2
  change 00 07 0E 05 0C 03 0A 01
         08 0F 06 0D 04 0B 02 09
      to 00 0D 0B 09 07 05 03 01
         0E 0C 0A 08 06 04 02 0F

]PR#6
...works...

As we saw earlier, the RWTS already has
"double" logic to accept either the
modified prologues/epilogues or the
standard ones. Even better (for us),
the code that checked for a timing bit
only triggered if it found a modified
epilogue. Now that we've converted the
disk to standard prologues/epilogues,
we don't need to change the RWTS at all
(beyond the sector order patch).

Quod erat liberandum.

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