💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › misc › Racter%20(4am%20c… captured on 2023-05-24 at 23:10:57.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

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

-----------------Racter----------------
A 4am crack                  2014-12-07
---------------------------------------

"Racter" is a 1985 text-based insanity
simulation developed by INRAC Corp. and
distributed by Mindscape. No one can be
told what Racter is; you have to see it
for yourself.

[The copy protection is identical to
"Rambo First Blood Part II," also
distributed by Mindscape. This write-up
is therefore quite similar to that one,
with a few updates because I have more
automated tools now.]

The original disk appears to be built
on Apple Pascal. At least, the boot
process looks like Pascal. It fills the
screen with null bytes, then clears the
screen and shows a solid cursor, then
continues to load the program.

COPYA fails miserably and immediately.
EDD 4 bit copy gives no read errors,
but the copy just reboots endlessly.

In my experience, programs do not
spontaneously reboot unless someone
tells them to.

Turning to my trusty Disk Fixer sector
editor, I go to "Input/Output Control"
(press "O") and set CHECKSUM ENABLED =
NO. This option ignores checksum bytes
and epilogue sequences -- as long as
the address and data prologue are
standard ("D5 AA 96" and "D5 AA AD",
respectively), this will allow me to
read each sector. And lo and behold, it
works! I can read the data from every
sector on every track.

Based on my limited experience cracking
other disks, I would guess that this
disk has

- Standard prologue bytes before the
  address and data fields [otherwise
  Copy ][+ sector editor would give
  read errors, even with the "DOS 3.3
  PATCHED" option]

- Non-standard epilogue bytes after the
  address and data fields [otherwise
  COPYA would work]

- Some secondary protection [otherwise
  the bit copy created with EDD 4 would
  work]

Given the (relatively) weak structural
protection, I used to turn to the DOS
3.3 master disk, patch the RWTS to
ignore checksums and epilogue bytes
(changing $B942 from "SEC" to "CLC"),
and run COPYA. Then, one fine day, and
completely by accident, I came across
an original disk with a bad sector. I
suppose this shouldn't surprise me.
These floppies are decades old by now;
it's amazing any of them work at all.

The point is, I shouldn't be using
tools that ignore potentially serious
read errors. There are other tools,
like Super Demuffin, that can convert a
disk like this (with non-standard
epilogue bytes) into a standard format.
It requires figuring out what the
actual epilogue bytes are, but it has
the advantage of surfacing a read error
if the original disk actually has a
read error.

So... no more COPYA+B942:18 patch. From
now on, it's Super Demuffin or Advanced
Demuffin to convert disks to a standard
format. My AUTOTRACE program will only
automate extraction of the RWTS from a
DOS 3.3-shaped bootloader, so let's see
if I can use Super Demuffin.

Super Demuffin is a cracker's utility
built on top of Locksmith Fast Disk
Copy. It takes a disk that uses non-
standard but uniform address and data
prologue and epilogue bytes, and it
converts it to a standard disk format.
I've included a copy on my work disk.

First, I'll need to find exactly what
those epilogue bytes are. Turning to
the Copy ][+ nibble editor:

                 --v--

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

TRACK: 01  START: 1F85  LENGTH: 015F

1F60: FF FF FF FF FF FF FF FF   VIEW
1F68: FF FF FF FF FF FF FF FF
1F70: FF FF FF FF FF FF FF FF
1F78: FF FF FF FF FF FF FF FF
1F80: FF FF FF FF FF D5 AA 96  <-1F85
                     ^^^^^^^^
             standard address prologue

1F88: AA AB AA AE AA AA AA AF
1F90: FF FF EB FF E7 F9 FE FF
      ^^^^^^^^
non-standard address epilogue

1F98: FF FF FF FF D5 AA AD E6
                  ^^^^^^^^
           standard data prologue

1FA0: F2 B7 D6 B9 FC DF EE CE

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

  A  TO ANALYZE DATA  ESC TO QUIT

  ?  FOR HELP SCREEN  /  CHANGE PARMS

  Q  FOR NEXT TRACK   SPACE TO RE-READ

                 --^--

(Not shown in the above screenshot, but
the data epilogue is also "FF FF EB".)

Some quick inspection suggests that all
tracks on the disk use the same non-
standard address and data epilogue
bytes. Now I can plug this information
into Super Demuffin.

When you first run Super Demuffin, it
asks for the parameters of the original
disk. In this case, the prologue bytes
are the same, but the epilogues are "FF
FF EB" instead of "DE AA EB".

                 --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
             *change from "DE AA"

      Data prologue: D5 AA AD

      Data epilogue: FF FF EB
                     ^^^^^
             *change from "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. It assumes that both
disks are in slot 6, and that drive 1
is the original and drive 2 is the
copy.

[S6,D1=original disk]
[S6,D2=blank disk]

                 --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...................................
[               ] PRESS [RESET] TO EXIT

                 --^--

There are two problems with this copy:

1. Depending on how the original disk
   was written, this copy may or may
   not be able to read itself. I may
   need to patch the disk's RWTS to
   deal with the fact that the disk is
   now in a standard format.

2. Even if it can read itself, it won't
   run. The copies I tried to make --
   even the bit copies -- just rebooted
   endlessly, which means there is some
   code being executed during boot to
   check if the disk is original.
   (Hint: it's not.)

Just by booting the copy, I can rule
out problem #1. The disk seems to read
itself just fine. It makes it exactly
as far as the failed bit copy -- far
enough to figure out that it's not an
original disk and reboot.

It's time for a little boot tracing.

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

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

]CALL -151





; only supports booting from slot 6
0801-   E0 60       CPX   #$60
0803-   F0 03       BEQ   $0808
0805-   4C E3 08    JMP   $08E3

; this is a loop that reuses the disk
; controller ROM routine to read
; several more sectors from track 0
0808-   AD 00 08    LDA   $0800
080B-   C9 06       CMP   #$06

; break out of read loop
080D-   B0 0A       BCS   $0819
080F-   69 02       ADC   #$02
0811-   8D 00 08    STA   $0800
0814-   E6 3D       INC   $3D

; jump to ROM to read the sector into
; the memory page given in zero page
; $3D (this jumps back to $801 when
; it finishes, which is why this read
; loop is actually a loop)
0816-   4C 5C C6    JMP   $C65C

; out of the read loop
0819-   A9 00       LDA   #$00

; don't know what this does yet
081B-   20 00 0B    JSR   $0B00

This is where I need to interrupt the
boot process.



; set up callback after boot0 breaks
; out of the initial read loop
96F8-   A9 4C       LDA   #$4C
96FA-   8D 19 08    STA   $0819
96FD-   A9 0A       LDA   #$0A
96FF-   8D 1A 08    STA   $081A
9702-   A9 97       LDA   #$97
9704-   8D 1B 08    STA   $081B

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

; callback is here
; turn off slot 6 drive motor
970A-   AD E8 C0    LDA   $C0E8

; relocate the boot1 code to hi-res
; page 1 so it will survive a reboot
970D-   A2 04       LDX   #$04
970F-   A0 00       LDY   #$00
9711-   B9 00 08    LDA   $0800,Y
9714-   99 00 28    STA   $2800,Y
9717-   C8          INY
9718-   D0 F7       BNE   $9711
971A-   EE 13 97    INC   $9713
971D-   EE 16 97    INC   $9716
9720-   CA          DEX
9721-   D0 EE       BNE   $9711

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




...reboots slot 6...
...reboots slot 5...

]BSAVE BOOT1,A$2800,L$400
]CALL-151





; usually holds current track (so the
; RWTS knows whether it needs to adjust
; the drive head, and in which
; direction)
0B00-   8D 78 04    STA   $0478

; save zero page
0B03-   A2 FF       LDX   #$FF
0B05-   B5 00       LDA   $00,X
0B07-   9D 00 30    STA   $3000,X
0B0A-   CA          DEX
0B0B-   D0 F8       BNE   $0B05
0B0D-   A9 0A       LDA   #$0A
0B0F-   85 50       STA   $50
0B11-   A6 2B       LDX   $2B

; turn on drive motor manually and go
; into read mode -- this is always
; suspicious (outside of RWTS code)
0B13-   BD 89 C0    LDA   $C089,X
0B16-   BD 8E C0    LDA   $C08E,X
0B19-   A9 97       LDA   #$97
0B1B-   85 48       STA   $48
0B1D-   A9 0B       LDA   #$0B
0B1F-   85 49       STA   $49
0B21-   A9 80       LDA   #$80
0B23-   85 51       STA   $51

; looks like the beginnings of a nibble
; check, with the failure path leading
; to $0B90
0B25-   C6 51       DEC   $51

; if zero page $51 counts down to 0,
; give up
0B27-   F0 67       BEQ   $0B90

; this subroutine positions the drive
; head to (presumably) where the nibble
; check needs it
0B29-   20 9F 0B    JSR   $0B9F

; if that failed, give up
0B2C-   B0 62       BCS   $0B90

; 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 COPYA 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
; just 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.)
0B2E-   A5 2E       LDA   $2E
0B30-   C9 05       CMP   #$05
0B32-   D0 F1       BNE   $0B25
0B34-   A0 00       LDY   #$00
0B36-   BD 8C C0    LDA   $C08C,X
0B39-   10 FB       BPL   $0B36
0B3B-   88          DEY

; give up
0B3C-   F0 52       BEQ   $0B90
0B3E-   C9 D5       CMP   #$D5
0B40-   D0 F4       BNE   $0B36
0B42-   A0 00       LDY   #$00
0B44-   BD 8C C0    LDA   $C08C,X
0B47-   10 FB       BPL   $0B44
0B49-   88          DEY

; give up
0B4A-   F0 44       BEQ   $0B90
0B4C-   C9 E7       CMP   #$E7
0B4E-   D0 F4       BNE   $0B44
0B50-   BD 8C C0    LDA   $C08C,X
0B53-   10 FB       BPL   $0B50
0B55-   C9 E7       CMP   #$E7

; give up
0B57-   D0 37       BNE   $0B90
0B59-   BD 8C C0    LDA   $C08C,X
0B5C-   10 FB       BPL   $0B59
0B5E-   C9 E7       CMP   #$E7

; give up
0B60-   D0 2E       BNE   $0B90

; kill some time to get out of sync
; with the "proper" start of nibbles)
0B62-   BD 8D C0    LDA   $C08D,X
0B65-   A0 10       LDY   #$10
0B67-   24 06       BIT   $06

; 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)
0B69-   BD 8C C0    LDA   $C08C,X
0B6C-   10 FB       BPL   $0B69
0B6E-   88          DEY

; give up
0B6F-   F0 1F       BEQ   $0B90
0B71-   C9 EE       CMP   #$EE
0B73-   D0 F4       BNE   $0B69

; check for nibble sequence stored
; in reverse order at $0B97
0B75-   A0 07       LDY   #$07
0B77-   BD 8C C0    LDA   $C08C,X
0B7A-   10 FB       BPL   $0B77
0B7C-   D1 48       CMP   ($48),Y

; give up
0B7E-   D0 10       BNE   $0B90
0B80-   88          DEY
0B81-   10 F4       BPL   $0B77

; restore zero page
0B83-   A2 FF       LDX   #$FF
0B85-   BD 00 30    LDA   $3000,X
0B88-   95 00       STA   $00,X
0B8A-   CA          DEX
0B8B-   D0 F8       BNE   $0B85

; if we made it this far, the nibble
; check passed -- load X register with
; $60 (presumably the slot number x 16)
; and exit gracefully
0B8D-   A2 60       LDX   #$60
0B8F-   60          RTS

; failure path is here -- decrement a
; counter and eventually give up and
; reboot
0B90-   C6 50       DEC   $50
0B92-   D0 8D       BNE   $0B21
0B94-   4C 00 C6    JMP   $C600

To sum up: if the nibble check fails
enough times, it gives up and reboots
(at $0B94). If the nibble check passes,
it just changes the X register to $60
(at $0B8D) and returns gracefully. It
doesn't even set or clear the carry
flag.

To bypass this, it should be enough to
change the original "JSR $0B00" to "STA
$0478" (which was the first instruction
at $0B00 and is what is usually there
in the boot0 code in the first place).

A lot of disks need this sort of
patching, and I got tired of doing it
manually, so I wrote a program to do it
for me. It is called Post-Demuffin
Patcher ("PDP" for short).

PDP prompts you to select a slot and
drive, then reads the demuffin'd disk,
checks for a modified DOS 3.3-shaped
RWTS, and applies the necessary patches
so the disk can read itself. It also
detects and bypasses some known nibble
checks, like the one on this disk.
I've included a copy of Post-Demuffin
Patcher on my work disk; the full
source code is currently available at
<https://archive.org/details/
PostDemuffinPatcher4am>.

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

]PR#5
...

]BRUN PDP

T00,S00,$1B change 20000B to 8D7804

(This is the actual output of the
program. Post-Demuffin Patcher prints
out the changes it is going to make
before it writes them to the disk.)

I should point out that Post-Demuffin
Patcher is really quite conservative in
making patches. It checks a lot of the
surrounding code before deciding to
patch a specific location. In the case
of bypassing this nibble check, it
checks every single byte of code up to
and including the JSR $0B00, to ensure
that the disk is using a known Pascal
bootloader up until that point. And
there were dozens of patches that it
didn't make to this disk (like RWTS
patches), because it decided they
weren't needed.

]PR#6

And it works. The disk boots and runs
with no complaint. There doesn't appear
to be any further protection. Hooray
for automation. (Oh, this is gonna get
good.)

Quod erat liberandum.

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