break up passport.a a bit [WIP]

This commit is contained in:
4am 2021-04-19 23:48:41 -04:00
parent 62a9b63498
commit 8a244c82b9
7 changed files with 893 additions and 907 deletions

372
src/adstyle.a Normal file
View File

@ -0,0 +1,372 @@
ADStyle
; We are now fairly confident that the RWTS in memory
; is normal enough to call, Advanced Demuffin style.
jsr IncProgress
lda #s_diskrwts
jsr PrintByID
;
; Check for protections in early boot that
; might indicate intentional bad sectors
; elsewhere in the disk that we should skip,
; or changes we need to make to the RWTS
; before we start.
;
jsr xHeredityDog
bcs +
lda #$05
sta gDisplayBytes
lda #s_lockitup
jsr PrintByID
+
jsr xSunburst
bcs +
lda #$04
sta gDisplayBytes
lda #s_sunburst
jsr PrintByID
+
jsr xOptimumRes
bcs +
lda #TRUE
sta gIsOptimum
lda #s_optimum
jsr PrintByID
+
jsr xSVE
bcs +
lda #s_sve
jsr PrintByID
lda #$CA
sta $BE5B
lda #$B6
sta $BE5C
+
jsr xRPS
bcs +
lda #$01
sta gDisplayBytes
lda #s_rps
jsr PrintByID
+
jsr xB660
jsr xB4BB
jsr xHarvey
jmp ReadWithRWTS
;-------------------------------
; xHeredityDog
; check for a protection check at $BB00
; which implies an unreadable T00,S0A
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if protection code was found
; C set if protection code was not found
;-------------------------------
!zone {
xHeredityDog
lda $08FE
clc
adc #$04
ldx #$16
ldy #$4A
jsr CompareMemory
!byte $F0,$05,$A2,$B2,$4C,$F0,$BB,$BD,$8C,$C0,$A9,WILDCARD
!byte $8D,$00,$02,$BD,$8C,$C0,$10,$FB,$C9,$EB,$D0,$F7,$BD,$8C
!byte $C0,$10,$FB,$C9,$D5,$D0,$EE,$BD,$8C,$C0,$10,$FB,$C9,$AA,$D0,$E5
!byte $A9,$4C,$A0,$00,$99,$00,$95,$88,$D0,$FA,$CE,$46,$BB,$AD,$46,$BB
!byte $C9,$07,$D0,$EC,$A9,$18,$8D,$42,$B9,$A9,$0A,$8D,$ED,$B7,$D0,$05
bcs .exit
lda #kSectorOptional
sta T00S0A
.exit
rts
}
;-------------------------------
; xSunburst
; check for a Sunburst RWTS
; which implies an unreadable T11,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if Sunburst RWTS was found
; C set otherwise
;-------------------------------
!zone {
xSunburst
lda $08FE
clc
adc #$03
ldx #$69
ldy #$2C
jsr CompareMemory
!byte $48,$A5,$2A,$4A,$A8,$B9,$29,$BA
!byte $8D,$6A,$B9,$8D,$84,$BC,$B9,$34
!byte $BA,$8D,$FC,$B8,$8D,$5D,$B8,$C0
!byte $11,$D0,$03,$A9,$02,$AC,$A9,$0E
!byte $8D,$C0,$BF,$68,$69,$00,$48,$AD
!byte $78,$04,$90,$2B
bcs .no
.yes
lda #kSectorOptional
sta T11S0F
.no
rts
}
;-------------------------------
; xOptimumRes
; check if disk has Optimum Resource bootloader
; which implies an unreadable T01,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if OptimumRes bootloader was found
; C set otherwise
;-------------------------------
!zone {
xOptimumRes
lda #$08
ldx #$5D
ldy #$0C
jsr CompareMemory
!byte $68,$85,WILDCARD,$68,$85,WILDCARD,$A0,$01
!byte $B1,WILDCARD,$85,$54
bcs .no
.yes
lda #kSectorOptional
sta T01S0F
.no
rts
}
;-------------------------------
; xB4BB
; check if disk changes RWTS in late boot after a nibble check
; (very messy because it needs to handle DOS 3.2 and 3.3 variants
; in either low or high memory)
;
; in: $0800..$08FF contains boot0
; either $3600..$3FFF or $B600..$BFFF contains boot1
; out: C clear if RWTS was modified in this routine
; C set otherwise
;-------------------------------
!zone {
xB4BB
lda gTrack
pha
lda gSector
pha
b4bbcompare
lda #$FF ; modified at runtime (in Inspect1)
ldx #$00
ldy #$20
jsr CompareMemory
!byte $D8,$A9,$DF,$48,$A9,$FF,$48,$A9
!byte $08,$85,$3D,$85,$43,$A9,$BF,$85
!byte $3F,$A9,$00,$85,$3C,$85,$42,$E6
!byte $42,$A9,$FE,$85,$3E,$A0,$00,$AD
bcs _b4bbexit
ldy gIsDOS32
beq .dos32
lda #$55 ; low byte of address that checks address prologue 1
sta b4bbmodify+1
lda #$91 ; low byte of address that checks address epilogue 1
sta b4bbmodify2+1
ldx #$00 ; track
ldy #$0C ; sector
bne .all ; always branches
.dos32
lda #$76 ; low byte of address that checks address prologue 1
sta b4bbmodify+1
lda #$B2 ; low byte of address that checks address epilogue 1
sta b4bbmodify2+1
ldx #$01 ; track
;;ldy #$00 ; sector
.all
lda #$00
sta gAddress
lda #$0C
adc #BASEPAGE
sta gAddress+1
jsr ReadSectorXY ; read sector so we can look for 'JMP $B4BB' marker
bcs _b4bbexit
lda #$0C
ldx #$84
ldy #$03
jsr compare
!byte $4C,$BB,$B4
bcs _b4bbexit
ldx #$02 ; track
ldy #$02 ; sector
lda gIsDOS32
bne .allb
.dos32b
ldy #$09 ; sector
.allb
jsr ReadSectorXY ; read sector to get address prologue 1 for rest of disk
bcs _b4bbexit
lda #$0C
adc #BASEPAGE
sta x0+2
x0 lda $FFC2 ; high byte modified at runtime (above)
cmp #$D5 ; some disks lie and manually set the prologue later
bne b4bbmodify ; passport-test-suite/SocMate Analogies Games.woz [Z=1] here
lda #TRUE
sta gPossibleB4BBBasic
lda #$BB
b4bbmodify
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
lda #$DE
b4bbmodify2
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
lda gIsDOS32
bne _b4bbexit
lda #kSectorCustomDOS32B4BB
sta T02S0C
_b4bbexit
pla
sta gSector
pla
sta gTrack
rts
}
;-------------------------------
; xB660
; Check if RWTS calls an extra routine at $B660
; after matching the first two data prologue
; nibbles. This routine can hang in an infinite
; loop if it's used to read an unprotected sector,
; so we need to force-switch to the built-in RWTS
; after reading all the protected sectors.
; (T00,S00-S09 are unprotected because they are
; read by the drive firmware.)
;
; in: $0800..$08FF contains boot0
; out: C clear if $B660 routine was found
; C set otherwise
;-------------------------------
!zone {
xB660
lda #$08
ldx #$60
ldy #$1A
jsr CompareMemory
!byte $BD,$8C,$C0,$10,$FB,$C9,$AD,$D0
!byte $F4,$A9,$F8,$3D,$8C,$C0,$D0,$02
!byte $EA,$EA,$EA,$EA,$BD,$8C,$C0,$2A
!byte $30,$02
bcs .no
.yes
lda #kSectorSwitchToBuiltinRWTS
sta T00S09
.no
rts
}
;-------------------------------
; xSVE
; check if disk has SVE bootloader
; which has a hook in the RWTS
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if SVE bootloader was found
; C set otherwise
;-------------------------------
!zone {
xSVE
lda #$BE
ldx #$5A
ldy #$03
jsr CompareMemory
!byte $4C,$71,$A9
rts
}
;-------------------------------
; xHarvey
; check if disk has Harvey protection
; which has a one-time RWTS swap
; after loading DOS
;
; in: $B600..$BFFF contains boot1
; out: RWTS may have been patched in memory
; all flags and registers clobbered
;-------------------------------
!zone {
xHarvey
lda #$B7
ldx #$47
ldy #$03
jsr CompareMemory
!byte $4C,$82,$A2
bcs .exit
ldx #$00
stx gAddress
inx
ldy #$02
lda #$09
sta gAddress+1
jsr ReadSectorXY ; read T01,S02 into $0900
bcs .exit
lda #$09
ldx #$32
ldy #$18
jsr CompareMemory
!byte $A9,WILDCARD
!byte $8D,$55,$B9
!byte $8D,$7A,$BC
!byte $A9,WILDCARD
!byte $8D,$5D,$B8
!byte $8D,$FC,$B8
!byte $A9,WILDCARD
!byte $8D,$60,$BC
!byte $4C,$84,$9D
bcs .exit
lda #$60
sta $0947 ; RTS instead of JMP
jsr $0932 ; call to apply RWTS patches
lda #kSectorSwitchToBuiltinRWTS
sta T02S0F
.exit rts
}
;-------------------------------
; xRPS
; check if disk has RPS protection
; (boot1 jumps to $B3C1 to change RWTS,
; epilogue checker jumps to $B6B3 to
; check timing bits, late DOS routes
; through nibble check at $B74B)
;
; in: $B600..$BFFF contains boot1
; out: C clear if protection found
; C set if protection was not found
;-------------------------------
!zone {
xRPS
lda #$B7
ldx #$47
ldy #$07
jsr CompareMemory
!byte $4C,$C1,$B3
!byte $60
!byte $48
!byte $A9,$02
bcs .exit
lda #kSectorOptional
sta T02S05
sta T02S0A
lda #kSectorSwitchToBuiltinRWTS
sta T02S04 ; some variants might auto-switch earlier, some need to be told
ldy #$FF
sty $BA29
iny
sty $BAFF
ldy #$3F
sty $BA96
.exit rts
}

View File

@ -246,219 +246,6 @@ IsUnformatted
rts
}
;-------------------------------
; xHeredityDog
; check for a protection check at $BB00
; which implies an unreadable T00,S0A
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if protection code was found
; C set if protection code was not found
;-------------------------------
!zone {
xHeredityDog
lda $08FE
clc
adc #$04
ldx #$16
ldy #$4A
jsr CompareMemory
!byte $F0,$05,$A2,$B2,$4C,$F0,$BB,$BD,$8C,$C0,$A9,WILDCARD
!byte $8D,$00,$02,$BD,$8C,$C0,$10,$FB,$C9,$EB,$D0,$F7,$BD,$8C
!byte $C0,$10,$FB,$C9,$D5,$D0,$EE,$BD,$8C,$C0,$10,$FB,$C9,$AA,$D0,$E5
!byte $A9,$4C,$A0,$00,$99,$00,$95,$88,$D0,$FA,$CE,$46,$BB,$AD,$46,$BB
!byte $C9,$07,$D0,$EC,$A9,$18,$8D,$42,$B9,$A9,$0A,$8D,$ED,$B7,$D0,$05
bcs .exit
lda #kSectorOptional
sta T00S0A
.exit
rts
}
;-------------------------------
; xSunburst
; check for a Sunburst RWTS
; which implies an unreadable T11,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if Sunburst RWTS was found
; C set otherwise
;-------------------------------
!zone {
xSunburst
lda $08FE
clc
adc #$03
ldx #$69
ldy #$2C
jsr CompareMemory
!byte $48,$A5,$2A,$4A,$A8,$B9,$29,$BA
!byte $8D,$6A,$B9,$8D,$84,$BC,$B9,$34
!byte $BA,$8D,$FC,$B8,$8D,$5D,$B8,$C0
!byte $11,$D0,$03,$A9,$02,$AC,$A9,$0E
!byte $8D,$C0,$BF,$68,$69,$00,$48,$AD
!byte $78,$04,$90,$2B
bcs .no
.yes
lda #kSectorOptional
sta T11S0F
.no
rts
}
;-------------------------------
; xOptimumRes
; check if disk has Optimum Resource bootloader
; which implies an unreadable T01,S0F
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if OptimumRes bootloader was found
; C set otherwise
;-------------------------------
!zone {
xOptimumRes
lda #$08
ldx #$5D
ldy #$0C
jsr CompareMemory
!byte $68,$85,WILDCARD,$68,$85,WILDCARD,$A0,$01
!byte $B1,WILDCARD,$85,$54
bcs .no
.yes
lda #kSectorOptional
sta T01S0F
.no
rts
}
;-------------------------------
; xB4BB
; check if disk changes RWTS in late boot after a nibble check
; (very messy because it needs to handle DOS 3.2 and 3.3 variants
; in either low or high memory)
;
; in: $0800..$08FF contains boot0
; either $3600..$3FFF or $B600..$BFFF contains boot1
; out: C clear if RWTS was modified in this routine
; C set otherwise
;-------------------------------
!zone {
xB4BB
lda gTrack
pha
lda gSector
pha
b4bbcompare
lda #$FF ; modified at runtime (in Inspect1)
ldx #$00
ldy #$20
jsr CompareMemory
!byte $D8,$A9,$DF,$48,$A9,$FF,$48,$A9
!byte $08,$85,$3D,$85,$43,$A9,$BF,$85
!byte $3F,$A9,$00,$85,$3C,$85,$42,$E6
!byte $42,$A9,$FE,$85,$3E,$A0,$00,$AD
bcs _b4bbexit
ldy gIsDOS32
beq .dos32
lda #$55 ; low byte of address that checks address prologue 1
sta b4bbmodify+1
lda #$91 ; low byte of address that checks address epilogue 1
sta b4bbmodify2+1
ldx #$00 ; track
ldy #$0C ; sector
bne .all ; always branches
.dos32
lda #$76 ; low byte of address that checks address prologue 1
sta b4bbmodify+1
lda #$B2 ; low byte of address that checks address epilogue 1
sta b4bbmodify2+1
ldx #$01 ; track
;;ldy #$00 ; sector
.all
lda #$00
sta gAddress
lda #$0C
adc #BASEPAGE
sta gAddress+1
jsr ReadSectorXY ; read sector so we can look for 'JMP $B4BB' marker
bcs _b4bbexit
lda #$0C
ldx #$84
ldy #$03
jsr compare
!byte $4C,$BB,$B4
bcs _b4bbexit
ldx #$02 ; track
ldy #$02 ; sector
lda gIsDOS32
bne .allb
.dos32b
ldy #$09 ; sector
.allb
jsr ReadSectorXY ; read sector to get address prologue 1 for rest of disk
bcs _b4bbexit
lda #$0C
adc #BASEPAGE
sta x0+2
x0 lda $FFC2 ; high byte modified at runtime (above)
cmp #$D5 ; some disks lie and manually set the prologue later
bne b4bbmodify ; passport-test-suite/SocMate Analogies Games.woz [Z=1] here
lda #TRUE
sta gPossibleB4BBBasic
lda #$BB
b4bbmodify
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
lda #$DE
b4bbmodify2
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
lda gIsDOS32
bne _b4bbexit
lda #kSectorCustomDOS32B4BB
sta T02S0C
_b4bbexit
pla
sta gSector
pla
sta gTrack
rts
}
;-------------------------------
; xB660
; Check if RWTS calls an extra routine at $B660
; after matching the first two data prologue
; nibbles. This routine can hang in an infinite
; loop if it's used to read an unprotected sector,
; so we need to force-switch to the built-in RWTS
; after reading all the protected sectors.
; (T00,S00-S09 are unprotected because they are
; read by the drive firmware.)
;
; in: $0800..$08FF contains boot0
; out: C clear if $B660 routine was found
; C set otherwise
;-------------------------------
!zone {
xB660
lda #$08
ldx #$60
ldy #$1A
jsr CompareMemory
!byte $BD,$8C,$C0,$10,$FB,$C9,$AD,$D0
!byte $F4,$A9,$F8,$3D,$8C,$C0,$D0,$02
!byte $EA,$EA,$EA,$EA,$BD,$8C,$C0,$2A
!byte $30,$02
bcs .no
.yes
lda #kSectorSwitchToBuiltinRWTS
sta T00S09
.no
rts
}
;-------------------------------
; IsEATrack6
; check if track 6 even exists
@ -477,108 +264,3 @@ IsEATrack6
sbc #5
cmp #1
+ rts
;-------------------------------
; xSVE
; check if disk has SVE bootloader
; which has a hook in the RWTS
;
; in: $0800..$08FF contains boot0
; $B600..$BFFF contains boot1
; out: C clear if SVE bootloader was found
; C set otherwise
;-------------------------------
!zone {
xSVE
lda #$BE
ldx #$5A
ldy #$03
jsr CompareMemory
!byte $4C,$71,$A9
rts
}
;-------------------------------
; xHarvey
; check if disk has Harvey protection
; which has a one-time RWTS swap
; after loading DOS
;
; in: $B600..$BFFF contains boot1
; out: RWTS may have been patched in memory
; all flags and registers clobbered
;-------------------------------
!zone {
xHarvey
lda #$B7
ldx #$47
ldy #$03
jsr CompareMemory
!byte $4C,$82,$A2
bcs .exit
ldx #$00
stx gAddress
inx
ldy #$02
lda #$09
sta gAddress+1
jsr ReadSectorXY ; read T01,S02 into $0900
bcs .exit
lda #$09
ldx #$32
ldy #$18
jsr CompareMemory
!byte $A9,WILDCARD
!byte $8D,$55,$B9
!byte $8D,$7A,$BC
!byte $A9,WILDCARD
!byte $8D,$5D,$B8
!byte $8D,$FC,$B8
!byte $A9,WILDCARD
!byte $8D,$60,$BC
!byte $4C,$84,$9D
bcs .exit
lda #$60
sta $0947 ; RTS instead of JMP
jsr $0932 ; call to apply RWTS patches
lda #kSectorSwitchToBuiltinRWTS
sta T02S0F
.exit rts
}
;-------------------------------
; xRPS
; check if disk has RPS protection
; (boot1 jumps to $B3C1 to change RWTS,
; epilogue checker jumps to $B6B3 to
; check timing bits, late DOS routes
; through nibble check at $B74B)
;
; in: $B600..$BFFF contains boot1
; out: C clear if protection found
; C set if protection was not found
;-------------------------------
!zone {
xRPS
lda #$B7
ldx #$47
ldy #$07
jsr CompareMemory
!byte $4C,$C1,$B3
!byte $60
!byte $48
!byte $A9,$02
bcs .exit
lda #kSectorOptional
sta T02S05
sta T02S0A
lda #kSectorSwitchToBuiltinRWTS
sta T02S04 ; some variants might auto-switch earlier, some need to be told
ldy #$FF
sty $BA29
iny
sty $BAFF
ldy #$3F
sty $BA96
.exit rts
}

196
src/crackme.a Normal file
View File

@ -0,0 +1,196 @@
ReadWithRWTS
lda #$22
jsr ChangeTrackNW
lda #$0F
ldx gIs13Sector
bne +
lda #$0C
+ jsr ChangeSector
lda #<T22S0F
sta checksector+1
lda #>T22S0F
sta checksector+2
.read
lda KEY
bpl .checkinfocom
bit STROBE
cmp #$e0 ;ignore backtick (MAME debug break)
beq .checkinfocom
jmp Cancel
.checkinfocom
lda gIsInfocom18
bne checksector
jsr VerifyInfocom18
bcc .passtrack
jmp FatalError
.passtrack
jmp .prevtrack
checksector
lda $FFFF ; status of current sector in sector map (modified above)
cmp #kSectorCustomFirst ; call a custom routine before deciding what to do with this sector?
bcc +
cmp #kSectorCustomLast
bcs +
jsr PreReadSector
+ pha ; replace status (on stack) with new status returned from PreReadSector
cmp #kSectorIgnore ; skip this sector?
beq nextsector
cmp #kSectorSwitchToBuiltinRWTS ; switch to built-in RWTS before reading this sector?
bne +
lda gTriedUniv
beq +
jsr SwitchToUniv
+ jsr ReadSector
bcc nextsector
;
; Uh oh, we got a read error. But do we care?
; If we just got to this track, check for whole-track protections.
;
ldx #$0F ;16-sector
lda gIs13Sector
beq .expect13
lda gIsDOS32
bne +
.expect13
ldx #$0C ;13-sector
+ cpx gSector
bne .checkoptional
stx .sub+1
jsr SkipTrack
bcs .checkoptional
; Skip this track (we already printed the reason)
lda #$00
jsr ChangeSector
lda checksector+1
sec
.sub sbc #$0F ;self-modified according to sectors per track
sta checksector+1
bcs +
dec checksector+2
+ jmp nextsector
; do this only *after* checking for track-skip
; to avoid fatal errors on unformatted tracks
.checkoptional
pla
pha
;
; Maybe we marked this sector as optional based
; on markers in the bootloader.
;
cmp #kSectorOptional
beq .optional
;
; Otherwise we're in the middle of a track, so try switching to
; the universal RWTS and see if that helps. (Many disks contain
; an RWTS that can't read the early tracks or sectors that
; contain the RWTS code, since those are loaded by the
; disk controller firmware.)
;
.tryuniversal
lda gIsDOS32 ; is this a DOS 3.2 disk?
beq .fatal ; yes, so read error is fatal
lda gTriedUniv ; have we tried the universal RWTS?
beq .maybedavidson ; yes, but check one last thing
jsr SwitchToUniv ; no, switch it in now
jmp .read ; and re-read this sector
.maybedavidson
jsr IDDavidson
bcc .optional
.fatal pla ; if we get to here, we've
jmp FatalError ; decided the read error is fatal
.optional
lda #s_optbad ; say we're skipping this
jsr PrintByID ; optional sector
; /!\ execution falls through here
nextsector
pla
lda checksector+1
bne .nodec
dec checksector+2
.nodec
dec checksector+1
ldy gSector
dey
tya
jsr ChangeSector
lda gSector
bmi .prevtrack
.linkread
jmp .read
.prevtrack
lda #$0F
ldx gIs13Sector
bne +
lda #$0C
+ jsr ChangeSector
ldy gTrack
dey
tya
jsr ChangeTrack
jsr IncProgress
lda gTrack
bmi Pass
cmp gLastTrack
bcs .linkread
Pass
bit gMode
bpl @passVerify
lda gRAMDiskRef
beq @printFinalMessage ; not using RAM disk, so we're done
; we've written the entire cracked disk as a file on the RAM disk,
; now a second pass to write that file out to the target disk drive
lda #s_writingto
jsr PrintByID
lda #s_slotanddrive
jsr PrintByID
jsr SwapProDOS ; ProDOS out -> in
jsr WriteRAMToDisk
jsr SwapProDOS ; ProDOS in -> out (preserves flags)
bcc @printFinalMessage
jmp FatalWriteError
@printFinalMessage
lda gPatchCount
beq @passWithZeroPatches
lda #s_passcrack ; 'crack complete'
!byte $2C
@passWithZeroPatches
lda #s_passcrack0 ; 'crack complete but no patches'
!byte $2C
@passVerify
lda #s_pass ; 'verification complete'
jsr PrintByID
jmp TheEnd
Cancel
lda #s_canceled
jsr PrintByID
jmp TheEnd
FatalError
lda #s_fail
jsr PrintByID
lda gTrack
cmp #$22
bne @TheEnd
lda gSector
cmp #$0F
beq @failont22s0f
ldx gIsDOS32
bne @TheEnd
cmp #$0C
bne @TheEnd
@failont22s0f
lda #s_fatal220f
jsr PrintByID
@TheEnd jmp TheEnd

View File

@ -30,6 +30,9 @@ PC_SETEOF = $02
FULL_ACCESS = $C3
; MLI error codes
MLI_IOERR = $27
MLI_NODEV = $28
MLI_WRITEPROT = $2B
ERR_FNF = $46
ERR_EOF = $4C
ERR_EXIST = $47

View File

@ -95,6 +95,9 @@ FirstMover
!source "progress.a"
!source "rwts.a"
!source "standarddelivery.a"
!source "adstyle.a"
!source "universalstyle.a"
!source "crackme.a"
ResetVector
ldx #$FF
@ -212,327 +215,6 @@ Reaction
jmp TheEnd
+ jmp IDBootloader ; /src/id/inspect0
;
; We are now fairly confident that the RWTS in memory
; is normal enough to call, Advanced Demuffin style.
;
ADStyle
jsr IncProgress
lda #s_diskrwts
jsr PrintByID
;
; Check for protections in early boot that
; might indicate intentional bad sectors
; elsewhere in the disk that we should skip,
; or changes we need to make to the RWTS
; before we start.
;
jsr xHeredityDog
bcs +
lda #$05
sta gDisplayBytes
lda #s_lockitup
jsr PrintByID
+
jsr xSunburst
bcs +
lda #$04
sta gDisplayBytes
lda #s_sunburst
jsr PrintByID
+
jsr xOptimumRes
bcs +
lda #TRUE
sta gIsOptimum
lda #s_optimum
jsr PrintByID
+
jsr xSVE
bcs +
lda #s_sve
jsr PrintByID
lda #$CA
sta $BE5B
lda #$B6
sta $BE5C
+
jsr xRPS
bcs +
lda #$01
sta gDisplayBytes
lda #s_rps
jsr PrintByID
+
jsr xB660
jsr xB4BB
jsr xHarvey
jmp ReadWithRWTS
UseUniversal
jsr IncProgress
jsr StartWithUniv
;
; On Dinkey-DOS disks (e.g. Ultima V, Times of Lore), we start with the
; universal RWTS then apply a patch in memory.
; These disks use a hybrid RWTS that alters the sector number in the
; address field based on the address epilogue. Once we normalize the
; sector numbers, no further patches are required, since the RWTS can also
; read unprotected disks. A separate patcher finds the actual code that
; alters the sector number to print it to the log.
;
lda gIsDinkeyDOS
bne +
jsr PatchUniversalRWTSForOrigin
bmi ReadWithRWTS ; always branches
;
; On TSR disks (e.g. Dawn Patrol, Dungeon), we start with the universal
; RWTS then apply a patch in memory.
;
+ lda gIsTSR
bne +
jsr PatchUniversalRWTSForTSR
;
; On pure 13-sector disks, we just hijack the read routine to perform a
; verification instead.
;
+ lda gIs13Sector
bne +
lda #<read13
sta jCallRWTS+1
lda #>read13
sta jCallRWTS+2
bne ReadWithRWTS ; always branches
;
; On other disks that use the universal RWTS for the entire disk, we use
; an adaptive RWTS that accepts any epilogue on the first sector but then
; enforces all other sectors to have the same epilogue.
;
+ jsr PatchUniversalRWTSForAdaptive
;
; Disable drive recalibration on bad sectors so we give up on bad sectors
; faster and detect unformatted or specially structured tracks faster.
;
jsr PatchUniversalRWTSForNoRecal
;
; Some disks have different epilogues on track 0, so we stop using the
; adaptive RWTS so we don't falsely accuse those disks of being damaged.
;
lda #kSectorResetAdaptiveRWTS
sta T00S0F
;
; Some disks have an intentionally invalid checksum on T00,S00 (read by
; the drive firmware, which doesn't verify it).
;
lda #kSectorIgnoreAddressChecksum
sta T00S00
;
; note: execution falls through here
;
ReadWithRWTS
lda #$22
jsr ChangeTrackNW
lda #$0F
ldx gIs13Sector
bne +
lda #$0C
+ jsr ChangeSector
lda #<T22S0F
sta checksector+1
lda #>T22S0F
sta checksector+2
.read
lda KEY
bpl .checkinfocom
bit STROBE
cmp #$e0 ;ignore backtick (MAME debug break)
beq .checkinfocom
jmp Cancel
.checkinfocom
lda gIsInfocom18
bne checksector
jsr VerifyInfocom18
bcc .passtrack
jmp FatalError
.passtrack
jmp .prevtrack
checksector
lda $FFFF ; status of current sector in sector map (modified above)
cmp #kSectorCustomFirst ; call a custom routine before deciding what to do with this sector?
bcc +
cmp #kSectorCustomLast
bcs +
jsr PreReadSector
+ pha ; replace status (on stack) with new status returned from PreReadSector
cmp #kSectorIgnore ; skip this sector?
beq nextsector
cmp #kSectorSwitchToBuiltinRWTS ; switch to built-in RWTS before reading this sector?
bne +
lda gTriedUniv
beq +
jsr SwitchToUniv
+ jsr ReadSector
bcc nextsector
;
; Uh oh, we got a read error. But do we care?
; If we just got to this track, check for whole-track protections.
;
ldx #$0F ;16-sector
lda gIs13Sector
beq .expect13
lda gIsDOS32
bne +
.expect13
ldx #$0C ;13-sector
+ cpx gSector
bne .checkoptional
stx .sub+1
jsr SkipTrack
bcs .checkoptional
; Skip this track (we already printed the reason)
lda #$00
jsr ChangeSector
lda checksector+1
sec
.sub sbc #$0F ;self-modified according to sectors per track
sta checksector+1
bcs +
dec checksector+2
+ jmp nextsector
; do this only *after* checking for track-skip
; to avoid fatal errors on unformatted tracks
.checkoptional
pla
pha
;
; Maybe we marked this sector as optional based
; on markers in the bootloader.
;
cmp #kSectorOptional
beq .optional
;
; Otherwise we're in the middle of a track, so try switching to
; the universal RWTS and see if that helps. (Many disks contain
; an RWTS that can't read the early tracks or sectors that
; contain the RWTS code, since those are loaded by the
; disk controller firmware.)
;
.tryuniversal
lda gIsDOS32 ; is this a DOS 3.2 disk?
beq .fatal ; yes, so read error is fatal
lda gTriedUniv ; have we tried the universal RWTS?
beq .maybedavidson ; yes, but check one last thing
jsr SwitchToUniv ; no, switch it in now
jmp .read ; and re-read this sector
.maybedavidson
jsr IDDavidson
bcc .optional
.fatal pla ; if we get to here, we've
jmp FatalError ; decided the read error is fatal
.optional
lda #s_optbad ; say we're skipping this
jsr PrintByID ; optional sector
; note: execution falls through here
nextsector
pla
lda checksector+1
bne .nodec
dec checksector+2
.nodec
dec checksector+1
ldy gSector
dey
tya
jsr ChangeSector
lda gSector
bmi .prevtrack
.linkread
jmp .read
.prevtrack
lda #$0F
ldx gIs13Sector
bne +
lda #$0C
+ jsr ChangeSector
ldy gTrack
dey
tya
jsr ChangeTrack
jsr IncProgress
lda gTrack
bmi Pass
cmp gLastTrack
bcs .linkread
Pass
bit gMode
bpl @passVerify
lda gRAMDiskRef
beq @printFinalMessage ; not using RAM disk, so we're done
; we've written the entire cracked disk as a file on the RAM disk,
; now a second pass to write that file out to the target disk drive
lda #s_writingto
jsr PrintByID
lda #s_slotanddrive
jsr PrintByID
jsr SwapProDOS ; ProDOS out -> in
jsr WriteRAMToDisk
jsr SwapProDOS ; ProDOS in -> out (preserves flags)
bcc @printFinalMessage
jmp FatalWriteError
@printFinalMessage
lda gPatchCount
beq @passWithZeroPatches
lda #s_passcrack ; 'crack complete'
!byte $2C
@passWithZeroPatches
lda #s_passcrack0 ; 'crack complete but no patches'
!byte $2C
@passVerify
lda #s_pass ; 'verification complete'
jsr PrintByID
jmp TheEnd
Cancel
lda #s_canceled
jsr PrintByID
jmp TheEnd
FatalError
lda #s_fail
jsr PrintByID
lda gTrack
cmp #$22
bne TheEnd
.failont22
lda gSector
cmp #$0F
beq .failont22s0f
ldx gIsDOS32
bne TheEnd
cmp #$0C
bne TheEnd
.failont22s0f
lda #s_fatal220f
jsr PrintByID
; /!\ execution falls through here
TheEnd
lda $C0E8
jsr CleanupFiles
@ -547,25 +229,6 @@ TheEnd
beq HandleRedoWithIgnore
jmp MainMenu
;-------------------------------
; CleanupFiles
;
; Cleans up open files (if any)
;
; in: ProDOS is NOT in memory
; out: ProDOS is NOT in memory
; all registers and flags clobbered
;-------------------------------
CleanupFiles
lda gHardDiskRef
ora gRAMDiskRef
beq +
jsr SwapProDOS ; ProDOS out -> in
jsr DeleteFileOnRAMDisk
jsr CloseFileOnHardDisk
jsr SwapProDOS ; ProDOS in -> out
+ rts
HandleRedoWithIgnore
jsr InitSectorMapWithIgnore
jmp Reaction
@ -594,6 +257,25 @@ RestartScan
txs
jmp ReadWithRWTS
;-------------------------------
; CleanupFiles
;
; Cleans up open files (if any)
;
; in: ProDOS is NOT in memory
; out: ProDOS is NOT in memory
; all registers and flags clobbered
;-------------------------------
CleanupFiles
lda gHardDiskRef
ora gRAMDiskRef
beq +
jsr SwapProDOS ; ProDOS out -> in
jsr DeleteFileOnRAMDisk
jsr CloseFileOnHardDisk
jsr SwapProDOS ; ProDOS in -> out
+ rts
;-------------------------------
; CleanExit
;
@ -614,107 +296,6 @@ CleanExit
!word +
+ !byte $04
;-------------------------------
; WriteTrack
;-------------------------------
MLI_IOERR = $27
MLI_NODEV = $28
MLI_WRITEPROT = $2B
WriteTrack
jsr AnalyzeTrack
WriteTrackNA ; entry point used by Special Delivery tracer
; to write track with 'N'o 'A'nalysis
bit gMode
bpl @exit ; don't write anything in verify mode
lda gSaidWriting
beq @doTheWriteThing ; only print 'writing to' message once
; we haven't yet printed any 'writing to...' message in the log, so
; figure out what that should look like and do it now
lda #s_writingto
jsr PrintByID
lda gHardDiskRef
beq @maybeWritingToRAMDisk
; we are writing to a file on a hard disk, so print the
; full pathname of that file
jsr PrintHardDiskImagePath
bvc @doneSaidWriting ; always branches
@maybeWritingToRAMDisk
lda gRAMDiskRef
beq @notWritingToRAMDisk
lda #s_ramdisk ; writing to (a file on) a RAM disk
!byte $2C
@notWritingToRAMDisk
lda #s_slotanddrive ; writing to a slot and drive
jsr PrintByID
@doneSaidWriting
lda #TRUE
sta gSaidWriting
@doTheWriteThing
jsr SwapProDOS ; ProDOS out -> in
jsr WriteTrackFirstPass
jsr SwapProDOS ; ProDOS in -> out
bcs FatalWriteError
@exit rts
;-------------------------------
; FatalWriteError
; in: A has MLI code (from WriteTrackFirstPass or WriteTrackSecondPass)
; out: does not return, exits via TheEnd
;-------------------------------
FatalWriteError
sta gDisplayBytes ; for use in error messages, if any
tax
lda #s_writeioerr
cpx #MLI_IOERR
beq .printerr
lda #s_writenodev
cpx #MLI_NODEV
beq .printerr
lda #s_writeprot
cpx #MLI_WRITEPROT
beq .printerr
lda #s_othermli
.printerr
pha
lda #s_writeerr
jsr PrintByID
pla
jsr PrintByID
jmp TheEnd
;-------------------------------
; ChangeTrack
; in: A = new track
;-------------------------------
ChangeTrack
sta .new+1
jsr WriteTrack
.new lda #$d1 ; modified at runtime
; note: execution falls through here
ChangeTrackNW ; "N"o "W"rite
sta gTrack
jsr ClearTSBuffer
rts
;-------------------------------
; ChangeSector
; in: A = new sector
;-------------------------------
ChangeSector
sta gSector
clc
adc #BASEPAGE
sta gAddress+1
rts
;-------------------------------
; AnalyzeTrack routine
; Looks at buffer in memory to detect known
@ -722,28 +303,31 @@ ChangeSector
; to work on standard disks.
; Prints through COUT
; Makes modifications in memory only.
; in: $BASEPAGE page contains one track worth of data
; out: if C set, no known protections were found and
; no modifications were made
; if C clear, at least one modification was made
; in: @BASEPAGE contains one track worth of data ($1000 bytes)
; gTrack contains track number
; out: if C set, no known protections were found and
; no modifications were made
; if C clear, at least one modification was made
;-------------------------------
AnalyzeTrack
lda gTrack
bne _applyToAll
_applyToT00
bne @applyToAll
; Track 0 patchers are stored compressed in memory
; then decompressed into $2000 when needed
lda #>AnalyzeT00
sta _byte_hi
lda #<AnalyzeT00
sta _byte_lo
jsr decrunch
jsr $2000
_applyToAll
; /!\ execution falls through here
@applyToAll
; run these modules in verify and crack mode
!source "patchers/t11diskvol.a" ; T11 && gIsRWTS only
!source "patchers/t02volumename.a" ; T02 && gIsBoot0 only
bit gMode
bmi +
jmp .checkPatchCount
jmp _checkPatchCount
+
; only run these modules in crack mode
!source "patchers/universale7.a"
@ -802,15 +386,16 @@ _applyToAll
!source "patchers/leisure.a" ; gIsProDOS && T22 only
!source "patchers/b4bbbasic.a" ; gPossibleB4BBBasic only
.checkPatchCount
_checkPatchCount
lda gPatchCount
beq .nopatches
beq @noPatches
clc
!byte $24 ; hide next SEC
.nopatches
@noPatches
sec ; set carry if nothing happened
rts
; utility functions used by several patchers
inx6 inx
inx5 inx
inx4 inx
@ -819,7 +404,6 @@ inx4 inx
inx
rts
universalrwts
!bin "../build/universalrwts.pak"
!source "exodecrunch.s"

View File

@ -88,170 +88,136 @@ endprotread
; assume all other things clobbered
;-------------------------------
PreReadSector
!zone {
cmp #kSectorResetAdaptiveRWTS
beq .reset
beq @reset
cmp #kSectorIgnoreAddressChecksum
beq IgnoreAddressChecksum
cmp #kSectorCustomDOS32B4BB
beq .b4bb
beq @b4bb
rts
.reset
@reset
jsr CopyUniversal
lda #kSectorRequired
rts
.b4bb
@b4bb
ldx jCallRWTS+2
dex
dex
dex
dex
stx .a+2
stx .b+2
stx @a+2
stx @b+2
ldx #$D5
.a stx $FF76
@a stx $FF76
ldx #$ED
.b stx $FFB2
.exit rts
}
@b stx $FFB2
rts
!zone {
IgnoreAddressChecksum
; out: A,Y preserved
; X clobbered
ldx #$00
stx $B98A
rts
}
!zone {
PatchUniversalRWTSForNoRecal
lda #$B0
sta $BDD2
lda #$30
sta $BDD3
;-------------------------------
; ChangeTrack
; in: A = new track
;-------------------------------
ChangeTrack
sta .new+1
jsr WriteTrack
.new lda #$d1 ; modified at runtime
; note: execution falls through here
ChangeTrackNW ; "N"o "W"rite
sta gTrack
jsr ClearTSBuffer
rts
}
!zone {
PatchUniversalRWTSForAdaptive
; out: N flag set
ldy #$09
- lda .addressepilogue, y
sta $B994, y
lda .dataepilogue, y
sta $B938, y
dey
bpl -
rts
.addressepilogue ; to $B994
!byte $8D,$91,$B9
!byte $A9,$AE
!byte $8D,$93,$B9
!byte $D0,$00
.dataepilogue ; to $B938
!byte $8D,$35,$B9
!byte $A9,$0A
!byte $8D,$37,$B9
!byte $18
!byte $60
}
!zone {
PatchUniversalRWTSForOrigin
; out: N=1
ldy #$0F
- lda .addressepilogue, y
sta $B990, y
dey
bpl -
ldy #$0A
- lda .dataepilogue, y
sta $B92F, y
dey
bpl -
rts
.addressepilogue ; to $B990
!byte $C9,$AB
!byte $D0,$0A
!byte $EA
!byte $BD,$8C,$C0
!byte $C9,$AB
!byte $F0,$95
!byte $D0,$00
!byte $18,$60
.dataepilogue ; to $B92F
!byte $18
!byte $60
!byte $38
!byte $A5,$2D
!byte $E9,$11
!byte $85,$2D
!byte $18
!byte $60
}
!zone {
PatchUniversalRWTSForTSR
; out: Z=0
lda #<tsr_callback
sta $BE8C
lda #>tsr_callback
sta $BE8D
rts
tsr_callback
pha
ldy gTrack
cpy #$05
bcc .normal
lda $F800, y
and #$42
bne +
lda #$42
+ ora #$B5
!byte $2C
.normal lda #$AD
sta $B8FC
pla
jmp $B9A0
}
SwitchToUniv
lda gSector
sta gDisplayBytes
lda #s_switch
!byte $2C ; hide next LDA
StartWithUniv
lda #s_builtin
jsr PrintByID
lda #TRUE
sta gTriedUniv
lda #FALSE
sta gIsProtDOS
; /!\ execution falls through here
CopyUniversal
lda #$B8
CopyUniversalAnywhere
sta universalrwts
;-------------------------------
; ChangeSector
; in: A = new sector
;-------------------------------
ChangeSector
sta gSector
clc
adc #$02
sta .cu+2
lda #>universalrwts
sta _byte_hi
lda #<universalrwts
sta _byte_lo
jsr decrunch
sty jCallRWTS+1
lda #$BD
sta jCallRWTS+2
ldy #$96
.culoop lda gNIBTable,y
.cu sta $d100,y ; set at runtime
iny
bne .culoop
adc #BASEPAGE
sta gAddress+1
rts
;-------------------------------
; WriteTrack
; in: none
;-------------------------------
WriteTrack
jsr AnalyzeTrack
WriteTrackNA ; entry point used by Special Delivery tracer
; to write track with 'N'o 'A'nalysis
bit gMode
bpl @exit ; don't write anything in verify mode
lda gSaidWriting
beq @doTheWriteThing ; only print 'writing to' message once
; we haven't yet printed any 'writing to...' message in the log, so
; figure out what that should look like and do it now
lda #s_writingto
jsr PrintByID
lda gHardDiskRef
beq @maybeWritingToRAMDisk
; we are writing to a file on a hard disk, so print the
; full pathname of that file
jsr PrintHardDiskImagePath
bvc @doneSaidWriting ; always branches
@maybeWritingToRAMDisk
lda gRAMDiskRef
beq @notWritingToRAMDisk
lda #s_ramdisk ; writing to (a file on) a RAM disk
!byte $2C
@notWritingToRAMDisk
lda #s_slotanddrive ; writing to a slot and drive
jsr PrintByID
@doneSaidWriting
lda #TRUE
sta gSaidWriting
@doTheWriteThing
jsr SwapProDOS ; ProDOS out -> in
jsr WriteTrackFirstPass
jsr SwapProDOS ; ProDOS in -> out
bcs FatalWriteError
@exit rts
;-------------------------------
; FatalWriteError
; in: A has MLI code (from WriteTrackFirstPass or WriteTrackSecondPass)
; out: does not return, exits via TheEnd
;-------------------------------
FatalWriteError
sta gDisplayBytes ; for use in error messages, if any
tax
lda #s_writeioerr
cpx #MLI_IOERR
beq .printerr
lda #s_writenodev
cpx #MLI_NODEV
beq .printerr
lda #s_writeprot
cpx #MLI_WRITEPROT
beq .printerr
lda #s_othermli
.printerr
pha
lda #s_writeerr
jsr PrintByID
pla
jsr PrintByID
jmp TheEnd
gTrack !byte $00
gSector !byte $00

183
src/universalstyle.a Normal file
View File

@ -0,0 +1,183 @@
UseUniversal
jsr IncProgress
jsr StartWithUniv
;
; On Dinkey-DOS disks (e.g. Ultima V, Times of Lore), we start with the
; universal RWTS then apply a patch in memory.
; These disks use a hybrid RWTS that alters the sector number in the
; address field based on the address epilogue. Once we normalize the
; sector numbers, no further patches are required, since the RWTS can also
; read unprotected disks. A separate patcher finds the actual code that
; alters the sector number to print it to the log.
;
lda gIsDinkeyDOS
bne +
jsr PatchUniversalRWTSForOrigin
bmi @doneUnivPatching ; always branches
;
; On TSR disks (e.g. Dawn Patrol, Dungeon), we start with the universal
; RWTS then apply a patch in memory.
;
+ lda gIsTSR
bne +
jsr PatchUniversalRWTSForTSR
;
; On pure 13-sector disks, we just hijack the read routine to perform a
; verification instead.
;
+ lda gIs13Sector
bne +
lda #<read13
sta jCallRWTS+1
lda #>read13
sta jCallRWTS+2
bne @doneUnivPatching ; always branches
;
; On other disks that use the universal RWTS for the entire disk, we use
; an adaptive RWTS that accepts any epilogue on the first sector but then
; enforces all other sectors to have the same epilogue.
;
+ jsr PatchUniversalRWTSForAdaptive
;
; Disable drive recalibration on bad sectors so we give up on bad sectors
; faster and detect unformatted or specially structured tracks faster.
;
jsr PatchUniversalRWTSForNoRecal
;
; Some disks have different epilogues on track 0, so we stop using the
; adaptive RWTS so we don't falsely accuse those disks of being damaged.
;
lda #kSectorResetAdaptiveRWTS
sta T00S0F
;
; Some disks have an intentionally invalid checksum on T00,S00 (read by
; the drive firmware, which doesn't verify it).
;
lda #kSectorIgnoreAddressChecksum
sta T00S00
@doneUnivPatching
jmp ReadWithRWTS
SwitchToUniv
lda gSector
sta gDisplayBytes
lda #s_switch
!byte $2C ; hide next LDA
; /!\ execution falls through here
StartWithUniv
lda #s_builtin
jsr PrintByID
lda #TRUE
sta gTriedUniv
lda #FALSE
sta gIsProtDOS
; /!\ execution falls through here
CopyUniversal
lda #$B8
; /!\ execution falls through here
CopyUniversalAnywhere
sta universalrwts
clc
adc #$02
sta .cu+2
lda #>universalrwts
sta _byte_hi
lda #<universalrwts
sta _byte_lo
jsr decrunch
sty jCallRWTS+1
lda #$BD
sta jCallRWTS+2
ldy #$96
.culoop lda gNIBTable,y
.cu sta $d100,y ; set at runtime
iny
bne .culoop
rts
PatchUniversalRWTSForNoRecal
lda #$B0
sta $BDD2
lda #$30
sta $BDD3
rts
PatchUniversalRWTSForAdaptive
; out: N flag set
ldy #$09
- lda @addressepilogue, y
sta $B994, y
lda @dataepilogue, y
sta $B938, y
dey
bpl -
rts
@addressepilogue ; to $B994
!byte $8D,$91,$B9
!byte $A9,$AE
!byte $8D,$93,$B9
!byte $D0,$00
@dataepilogue ; to $B938
!byte $8D,$35,$B9
!byte $A9,$0A
!byte $8D,$37,$B9
!byte $18
!byte $60
PatchUniversalRWTSForOrigin
; out: N=1
ldy #$0F
- lda @addressepilogue, y
sta $B990, y
dey
bpl -
ldy #$0A
- lda @dataepilogue, y
sta $B92F, y
dey
bpl -
rts
@addressepilogue ; to $B990
!byte $C9,$AB
!byte $D0,$0A
!byte $EA
!byte $BD,$8C,$C0
!byte $C9,$AB
!byte $F0,$95
!byte $D0,$00
!byte $18,$60
@dataepilogue ; to $B92F
!byte $18
!byte $60
!byte $38
!byte $A5,$2D
!byte $E9,$11
!byte $85,$2D
!byte $18
!byte $60
PatchUniversalRWTSForTSR
; out: Z=0
lda #<@tsr_callback
sta $BE8C
lda #>@tsr_callback
sta $BE8D
rts
@tsr_callback
pha
ldy gTrack
cpy #$05
bcc @normal
lda $F800, y
and #$42
bne +
lda #$42
+ ora #$B5
!byte $2C
@normal lda #$AD
sta $B8FC
pla
jmp $B9A0