💾 Archived View for mirrors.apple2.org.za › active › 4am › images › games › adventure › Troll's%20Ta… captured on 2024-05-26 at 17:34:55.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

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

--------------Troll's Tale-------------
A 4am crack                  2014-08-13
---------------------------------------

"Troll's Tale" is a 1983 adventure game 
distributed by Sierra On-Line.

[The copy protection is identical to
"Piece of Cake" and "Piece of Cake
Math," which were distributed by
Springboard Software. Which is
interesting, because AFAIK those were
two unrelated companies. This write-up
is therefore quite similar to that one,
with a few corrections.]

COPYA fails immediately with a disk
read error. EDD 4 bit copy gives a read
error on track $0A but seems OK on all
other tracks. However, the bit copy
does not work. It boots as if it's
loading DOS 3.3, then displays an
inverse "A" in bottom-right corner,
then exits to a BASIC prompt with no
DOS loaded.

My trusty Copy ][+ sector editor in
"DOS 3.3 PATCHED" mode (press "P" to
get to the Sector Editor Patcher) can
read tracks 0-2, but nothing else.

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

For those of you just tuning in, my
work disk uses a custom program that I
affectionately call "AUTOTRACE" to
automate the process of boot tracing as
far as possible. For some disks, this
just captures track 0, sector 0 (saved
in a file called "BOOT0") and stops.
For other disks that load in the same
way that an unprotected DOS 3.3 disk
loads, it captures the next stage of
the boot process as well (in a file
called "BOOT1"). BOOT1 contains sectors
0-9 on track 0, which are loaded into
memory at $B600..$BFFF. This generally
contains the RWTS routines which the
program uses to read the rest of the
disk.

If the RWTS is fairly normal as well
(and my AUTOTRACE program just spot-
checks a few memory locations to guess
at its "normalcy"), there's a good
chance I'll be able to use a tool
called Advanced Demuffin (written in
1983 by The Stack) to convert the disk
from whatever weird format it uses to
store its sector data into a standard
disk readable by unprotected DOS 3.3
disks or any other third-party tools.
In this case, AUTOTRACE extracts the
RWTS routines (generally loaded from
track 0, sectors 2-9 into $B800..$BFFF)
and saves *that* into a third file
called "RWTS".

If anything looks fishy or non-
standard, AUTOTRACE just stops, and I
have to check the files it saved so far
to determine why. But in this case, it
ran all the way through, automatically
capturing BOOT0, BOOT1, and RWTS files.
Now I can use Advanced Demuffin to
convert the disk to a standard format.
(It uses the disk's own RWTS to read
the original, then a standard DOS 3.3-
compatible RWTS to write out the data,
sector by sector.)

But wait, there's more! The latest
feature I added to my AUTOTRACE program
is automatic IOB module creation. What
the heck is an IOB module? Well, the
author of Advanced Demuffin anticipated
that he couldn't anticipate everything,
so he made the program extensible.

Quoting from the Advanced Demuffin
softdocs (included on my work disk):

                 --v--

An IOB module is an interface for the
source RWTS. Advanced Demuffin uses the
IOB module to set up the IOB table and
jump to RWTS.  The IOB module is stored
from $1400-$14FB. When Advanced
Demuffin loads in a IOB module, it
reads the first sector of the file off
the track-sector list and stores it at
$13FC-$14FB. When Advanced Demuffin
wants to read a sector it JSRs to the
IOB module with the phase number,
sector number, and the page number
stored in the A, Y and X registers
respectively. Since the source drive
always has to be drive one, Advanced
Demuffin can make the IOB module very
compact. After it gets the page,track
and sector Advanced Demuffin sets up
the IOB for RWTS using this infor-
mation, and JMPs to RWTS. (It jumps
instead of JSRing, because it lets the
RWTS do the RTS.) Here is a list of the
IOB module that is built in to Advanced
Demuffin:

; Convert phase # to track #
1400-   4A          LSR

; Store track number
1401-   8D 22 0F    STA   $0F22

; Store sector number
1404-   8C 23 0F    STY   $0F23

; Store page number
; [note: original docs have incorrect
;        hex opcode on this line]
1407-   8E 27 0F    STX   $0F27

140A-   A9 01       LDA   #$01

; Store the drive number
140C-   8D 20 0F    STA   $0F20

; Store the read code
140F-   8D 2A 0F    STA   $0F2A

; With high byte of IOB
1412-   A9 0F       LDA   #$0F

; With low byte of IOB
1414-   A0 1E       LDY   #$1E

; Goto RWTS
1416-   4C 00 BD    JMP   $BD00

                 --^--

Basically, Advanced Demuffin only knows
how to call a custom RWTS if it

1. is loaded at $B800..$BFFF

2. uses a standard RWTS parameter table

3. has an entry point at $BD00 that
   takes the address of the parameter
   tables in A and Y

4. doesn't require initialization

As it turns out, that covers a *lot* of
copy protected disks, but it doesn't
cover this one because the RWTS on disk
is loaded at $3800..$3FFF and has its
entry point at $3D00. If I told
Advanced Demuffin to load this RWTS at
$B800 and call it at $BD00, it would
crash quite spectacularly.

So, I added a check to AUTOTRACE to
detect that the RWTS is loaded in a
non-standard location (lines 279-300 in
the HELLO program on my work disk) and
automatically create an IOB file that
can tell Advanced Demuffin how to
access it. Here's what it looks like:

]BLOAD IOB,A$1400
]CALL -151



; Most of this is identical to the
; standard IOB module that comes with
; Advanced Demuffin (explained above).
1400-   4A          LSR
1401-   8D 22 0F    STA   $0F22
1404-   8C 23 0F    STY   $0F23
1407-   8E 27 0F    STX   $0F27
140A-   A9 01       LDA   #$01
140C-   8D 20 0F    STA   $0F20
140F-   8D 2A 0F    STA   $0F2A

; One problem with having an RWTS at
; $3800..$3FFF is that that range is
; normally used to store track data
; during the copy process. If we just
; let Advanced Demuffin run, it will
; overwrite the custom RWTS almost
; immediately and crash. In the
; ADVANCED DEMUFFIN TECH NOTES (also
; included on my work disk), the author
; mentions that you can control how
; many sectors Advanced Demuffin reads
; at a time, and where it puts it in
; memory. Normally $1CF0 is $20 and
; $1CF1 is $90, meaning that it will
; copy 7 tracks worth of data at a time
; into $2000..$8FFF. Changing the end
; parameter to $30 will only copy one
; track at a time, but has the distinct
; advantage of not overwriting the RWTS
; and crashing.
1412-   A9 30       LDA   #$30
1414-   8D F1 1C    STA   $1CF1

; get the address of the RWTS parameter
; table at $0F1E and call the RWTS
; entry point at $3D00 (instead of the
; usual $BD00)
1417-   A9 0F       LDA   #$0F
1419-   A0 1E       LDY   #$1E
141B-   4C 00 3D    JMP   $3D00

Now I can use Advanced Demuffin to
convert the disk to a standard format.
It uses the disk's own RWTS to read the
original (stored in the RWTS file,
accessed via the IOB module), then a
standard DOS 3.3-compatible RWTS to
write out the data, sector by sector.

[S6,D1=my work disk]

]BRUN ADVANCED DEMUFFIN 1.1

--> LOAD NEW RWTS MODULE
    At $38, load "RWTS"
    from D1

--> LOAD NEW IOB MODULE
    load "IOB"
    from D1

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

--> CONVERT DISK

--> CHANGE DEFAULT VALUES? N

This disk is 16 sectors, and the
default options (copy the entire disk,
all tracks, all sectors) don't need to
be changed unless something goes
horribly wrong.

                 --v--

ADVANCED DEMUFFIN 1.1  - COPYRIGHT 1983
WRITTEN BY THE STACK -CORRUPT COMPUTING
=======PRESS ANY KEY TO CONTINUE=======
TRK:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC1:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC2:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC3:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC4:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC5:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC6:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC7:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC8:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC9:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCA:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCB:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCC:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCD:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCE:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCF:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
=======================================
16 SC $00,$00 TO $22,$0F BY $01 TO DRV2

                 --^--

This is really not going well. Remember
when I said the default options don't
need to be changed unless something
goes horribly wrong? (Seriously, I just
said that, like, a minute ago.) This is
what "horribly wrong" looks like. The
RWTS on the disk can't read, well, the
majority of the disk. Perhaps I was too
hasty in relying on my automated tools.
Perhaps there is more to this disk than
meets the eye.

Let's back up.

]PR#5





3700-   8E E9 37    STX   $37E9
3703-   8E F7 37    STX   $37F7
3706-   A9 01       LDA   #$01
3708-   8D F8 37    STA   $37F8
370B-   8D EA 37    STA   $37EA
370E-   AD E0 37    LDA   $37E0
3711-   8D E1 37    STA   $37E1
3714-   A9 02       LDA   #$02
3716-   8D EC 37    STA   $37EC
3719-   A9 04       LDA   #$04
371B-   8D ED 37    STA   $37ED
371E-   AC E7 37    LDY   $37E7
3721-   88          DEY
3722-   8C F1 37    STY   $37F1
3725-   A9 01       LDA   #$01
3727-   8D F4 37    STA   $37F4
372A-   8A          TXA
372B-   4A          LSR
372C-   4A          LSR
372D-   4A          LSR
372E-   4A          LSR
372F-   AA          TAX
3730-   A9 00       LDA   #$00
3732-   9D F8 04    STA   $04F8,X
3735-   9D 78 04    STA   $0478,X
3738-   20 93 37    JSR   $3793

Gah. I'm so comfortable tracing boot1
code in the $B700 range. But this...
this is like waking up in a parallel
universe where everything is just
slightly different and Robin Williams
is still alive. Anyway, this is all
bog standard so far. $3793 is the
multi-sector read routine that reads
the rest of DOS backwards starting at
T02,S04. The RWTS parameter table
starts at $37E8.

373B-   A2 FF       LDX   #$FF
373D-   9A          TXS
373E-   8E EB 37    STX   $37EB
3741-   4C C8 3F    JMP   $3FC8
3744-   20 89 FE    JSR   $FE89
3747-   4C 03 1B    JMP   $1B03

That last line looks suspicious, but
it's actually not. So far, this code is
identical to the DOS 3.3 master disk.
The routine at $1B03 is what figures
out how much memory there is and moves
DOS as high as possible.

It makes sense that I haven't found
anything unusual yet. Evidence so far
suggests that the RWTS on disk can read
tracks 0-2 (which is where it's loading
DOS), then it switches to a different
RWTS that can read the rest of the
disk. So whatever this disk is doing to
modify its RWTS or load a new one, it's
going to do it after loading DOS. And I
need to find out where.

But that means I need to trace the boot
even further.



; set up callback #1 after boot0 is
; loaded
96F8-   A9 4C       LDA   #$4C
96FA-   8D 4A 08    STA   $084A
96FD-   A9 0A       LDA   #$0A
96FF-   8D 4B 08    STA   $084B
9702-   A9 97       LDA   #$97
9704-   8D 4C 08    STA   $084C

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

; callback #1 is here --
; modify the boot1 code to reboot to my
; work disk after it loads DOS
970A-   A9 4C       LDA   #$4C
970C-   8D 47 37    STA   $3747
970F-   A9 00       LDA   #$00
9711-   8D 48 37    STA   $3748
9714-   A9 C5       LDA   #$C5
9716-   8D 49 37    STA   $3749

; continue the boot
9719-   6C FD 08    JMP   ($08FD)




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

]BSAVE BOOT2,A$1B00,L$2500

]CALL -151
...

The routine at $1B03 seems unmodified
(from the DOS 3.3 master disk). After
it completes, it jumps to $1D84.



1D84-   4C BB B4    JMP   $B4BB

I'm pretty sure *that's* not normal.
But wait, I can't see what it is yet
because I haven't run the routine at
$1B03 to move DOS up to higher memory.
(Also: despite the fact that this disk
loads DOS into low memory, this code
right here assumes that DOS was moved
to high memory. So why not just load it
there in the first place? Weird. If
this is part of the copy protection,
maybe it was bolted on after the fact?)

I'm going to see if I can run the DOS
relocation routine in memory without
having to write another layer of boot
tracing.




<beep>

Success! Let's see what's at $B4BB.



; overwriting the instruction that just
; called this routine -- highly suspect
B4BB-   A9 AD       LDA   #$AD
B4BD-   8D 84 9D    STA   $9D84
B4C0-   A9 E9       LDA   #$E9
B4C2-   8D 85 9D    STA   $9D85
B4C5-   A9 B7       LDA   #$B7
B4C7-   8D 86 9D    STA   $9D86

; overwriting most of the $B700 code?
; also suspicious
B4CA-   A2 00       LDX   #$00
B4CC-   BD BB B3    LDA   $B3BB,X
B4CF-   5E BB 33    LSR   $33BB,X
B4D2-   1E BB B3    ASL   $B3BB,X
B4D5-   9D 00 B7    STA   $B700,X
B4D8-   E8          INX
B4D9-   E0 B5       CPX   #$B5
B4DB-   90 EF       BCC   $B4CC
B4DD-   D8          CLD
B4DE-   AD FF CF    LDA   $CFFF

; overwriting the language card
B4E1-   AD 81 C0    LDA   $C081
B4E4-   AD 81 C0    LDA   $C081
B4E7-   A2 00       LDX   #$00
B4E9-   BD 00 F8    LDA   $F800,X
B4EC-   1E BB 34    ASL   $34BB,X
B4EF-   9D 00 F8    STA   $F800,X
B4F2-   E8          INX
B4F3-   D0 F4       BNE   $B4E9
B4F5-   EE EB B4    INC   $B4EB
B4F8-   EE F1 B4    INC   $B4F1
B4FB-   D0 EA       BNE   $B4E7

; hmm
B4FD-   AD 00 B7    LDA   $B700
B500-   F0 12       BEQ   $B514

OK, I need to know whether this branch
is taken. Let's break here and see.







B700- 00

OK, so we continue to $B514.



; set reset vector (both of them at
; $03F2 and $FFFC)
B514-   A9 BF       LDA   #$BF
B516-   8D FC FF    STA   $FFFC
B519-   8D F2 03    STA   $03F2
B51C-   A9 9D       LDA   #$9D
B51E-   8D F3 03    STA   $03F3
B521-   8D FD FF    STA   $FFFD
B524-   49 A5       EOR   #$A5
B526-   8D F4 03    STA   $03F4

; Aha! Fiddling with RWTS parameters!
B529-   AC 82 C0    LDY   $C082
B52C-   A0 DE       LDY   #$DE
B52E-   8C 91 B9    STY   $B991 <- RWTS
B531-   20 5E B7    JSR   $B75E
B534-   4C 6F B7    JMP   $B76F

The value at $B991 is one of the
address epilogue bytes.



; Double aha! More RWTS fiddling!
B75E-   AE 07 B7    LDX   $B707
B761-   8E 55 B9    STX   $B955 <- RWTS
B764-   AD 97 A3    LDA   $A397
B767-   C9 60       CMP   #$60
B769-   D0 03       BNE   $B76E
B76B-   8D 62 B7    STA   $B762
B76E-   60          RTS

The value at $B955 is one of the
address prologue bytes.



; what have we here?
B76F-   2C 06 B7    BIT   $B706
B772-   10 20       BPL   $B794
B774-   AE 03 B7    LDX   $B703

; 1
B777-   20 37 B5    JSR   $B537
B77A-   C9 06       CMP   #$06
B77C-   B0 23       BCS   $B7A1
B77E-   AE 04 B7    LDX   $B704

; 2
B781-   20 37 B5    JSR   $B537
B784-   C9 06       CMP   #$06
B786-   90 19       BCC   $B7A1
B788-   AE 05 B7    LDX   $B705

; 3
B78B-   20 37 B5    JSR   $B537
B78E-   C9 06       CMP   #$06
B790-   B0 0F       BCS   $B7A1
B792-   90 0A       BCC   $B79E
B794-   AE 04 B7    LDX   $B704

; 4
B797-   20 37 B5    JSR   $B537
B79A-   C9 02       CMP   #$02
B79C-   D0 03       BNE   $B7A1

; continue to normal boot
B79E-   4C 84 9D    JMP   $9D84

So what's at $B537 that's so important
that we need to call it up to 4 times?
I'm guessing it's a nibble check.



; read a sector
B537-   8E EC B7    STX   $B7EC
B53A-   A9 00       LDA   #$00
B53C-   8D F4 B7    STA   $B7F4
B53F-   A9 B7       LDA   #$B7
B541-   A0 E8       LDY   #$E8
B543-   20 B5 B7    JSR   $B7B5
B546-   AE E9 B7    LDX   $B7E9

; turn on drive motor manually
; (suspicious)
B549-   BD 89 C0    LDA   $C089,X
B54C-   BD 8E C0    LDA   $C08E,X

; set some counters
B54F-   A9 19       LDA   #$19
B551-   85 0D       STA   $0D
B553-   A0 00       LDY   #$00
B555-   84 09       STY   $09
B557-   A0 A0       LDY   #$A0

; oh look, a nibble check
B559-   BD 8C C0    LDA   $C08C,X
B55C-   10 FB       BPL   $B559
B55E-   49 FF       EOR   #$FF
B560-   F0 1C       BEQ   $B57E
B562-   E6 09       INC   $09
B564-   F0 24       BEQ   $B58A
B566-   BD 8C C0    LDA   $C08C,X
B569-   10 FB       BPL   $B566
B56B-   BD 8C C0    LDA   $C08C,X
B56E-   10 FB       BPL   $B56B
B570-   BD 8C C0    LDA   $C08C,X
B573-   10 FB       BPL   $B570
B575-   BD 8C C0    LDA   $C08C,X
B578-   10 FB       BPL   $B575
B57A-   49 FF       EOR   #$FF
B57C-   D0 0C       BNE   $B58A
B57E-   C8          INY
B57F-   D0 D8       BNE   $B559
B581-   C6 0D       DEC   $0D
B583-   D0 D4       BNE   $B559
B585-   A5 09       LDA   $09
B587-   18          CLC
B588-   90 02       BCC   $B58C

; success path is here (failure path
; skips over this and goes to $B58C)
B58A-   A9 FF       LDA   #$FF
B58C-   48          PHA
B58D-   BD 88 C0    LDA   $C088,X
B590-   68          PLA
B591-   60          RTS

OK, two things here. First of all,
nothing happens if the nibble check
succeeds. There are no long-term side
effects. It just continues booting. So
I can just bypass the whole damn thing,
which is nice.

Second, I can create the RWTS I need to
read the rest of the disk. I only need
to change two bytes.

[rebooting because I've destroyed my
work disk's DOS in memory]


...

]BLOAD RWTS,A$3800

]CALL -151









[S6,D1=my work disk]

--> LOAD NEW RWTS MODULE
    At $38, load "RWTS 3+"
    from D1

--> LOAD NEW IOB MODULE
    load "IOB"
    from D1

[S6,D1=original disk]
[S6,D2=demuffin'd copy with tracks 0-2]

--> CHANGE DEFAULT VALUES? Y

ADVANCED DEMUFFIN 1.1  -  COPYRIGHT 1983
WRITTEN BY THE STACK - CORRUPT COMPUTING
========================================


INPUT ALL VALUES IN HEX


SECTORS PER TRACK? (13/16) 16

START TRACK: $03
              ^^
              ++-- we have tracks 0-2
                   already

START SECTOR: $00

END TRACK: $22
END SECTOR: $0F

INCREMENT: 1

MAX # OF RETRIES: 0

COPY FROM DRIVE 1
TO DRIVE: 2
========================================
16 SC $03,$00 TO $22,$0F BY $01 TO DRV 2


Now press RETURN to start the copy...

                 --v--

ADVANCED DEMUFFIN 1.1  - COPYRIGHT 1983
WRITTEN BY THE STACK -CORRUPT COMPUTING
=======PRESS ANY KEY TO CONTINUE=======
TRK:   .......R........................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:   .......R........................
SC1:   .......R........................
SC2:   .......R........................
SC3:   .......R........................
SC4:   .......R........................
SC5:   .......R........................
SC6:   .......R........................
SC7:   .......R........................
SC8:   .......R........................
SC9:   .......R........................
SCA:   .......R........................
SCB:   .......R........................
SCC:   .......R........................
SCD:   .......R........................
SCE:   .......R........................
SCF:   .......R........................
=======================================
16 SC $03,$00 TO $22,$0F BY $01 TO DRV2

                 --^--

Damn it, now what? Wait, I remember EDD
4 had problems on track $0A as well.
Firing up the Copy ][+ nibble editor
and looking at track $0A on the
original disk, it appears that it is
entirely unformatted. I can't read it
because there's nothing to read. OK,
let's zero out that track and move on.

Next up: I need to patch the RWTS to be
able to read the disk, now that the
entire disk is in a standard format.
The only thing non-standard about the
RWTS on the original disk was that it
had "ED" instead of "DE" for one of the
epilogue bytes. (The other oddities
where only changed in memory by the
copy protection routine, which I'm
going to bypass.)

T00,S03,$91 change "ED" to "DE"

And finally, I need to bypass the copy
protection by changing the instruction
at $1D84 back to the original code that
matches the DOS 3.3 master disk.

T00,S0C,$84 change "4C BB B4"
                to "AD E9 37"

Quod erat liberandum.

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