passport/src/wholetrack.a

373 lines
9.7 KiB
Plaintext
Executable File

;-------------------------------
; Identification routines for various whole-track
; protections and other frivolities.
;
; The main entry point is SkipTrack, which is
; called when the last sector ($0F or $0C) of a
; newly-seeked track is unexpectedly unreadable.
; (All the words in that sentence are important.)
;
; This file also contains low-level subroutines
; that require precise timing. There are
; assemble-time guards around the timing-sensitive
; instructions, which means that changes to this
; file may result in fatal assembler build errors
; because you moved code that can't cross a page
; boundary and now it crosses a page boundary.
;-------------------------------
;-------------------------------
; SkipTrack
; out: C clear if we should skip this track
; C set if we should not skip this track
;-------------------------------
SkipTrack
; don't look for whole-track protections on track 0, that's silly
lda gTrack
sec
beq @linknoskip
;
; Electronic Arts protection track?
;
jsr IsWideTrack
lda #s_widetrack
bcc @print
;
; Nibble count track?
;
jsr JustTheSameDamnThingOverAndOver
lda #s_sync
bcc @print
;
; Unexepcted 13-sector track on a 16-sector disk?
; (Micrograms likes to do this)
;
jsr Unexpected5And3InBaggingArea
lda #s_unexpected5and3
bcc @print
;
; RW18-format track?
;
jsr VerifyInfocom18
lda #s_rw18
bcc @print
;
; Unformatted track?
;
jsr IsUnformatted
@linknoskip
bcs @donotskip
;
; $F7F6EFEAAB protection track?
; (initially presents as unformatted, needs separate test because it
; triggers special handling)
;
jsr IsF7F6
lda #s_unformat
bcs @print
lda #s_f7
bit gMode
bpl @print
bvc @print
; if we're in 'crack' mode, restart the scan to find the protection code
bvs SetupF7F6SecondRound ; always branches
@print sta +
jsr PrintByID
+ !byte $FD ; SMC
;
; Skipping T22 on a ProDOS disk might indicate the presence of a
; Gamco Industries protection elsewhere on the disk. Different
; Gamco disks present as different types of weirdness on T22 --
; EEEF, sync, or even unformatted. (The actual protection is just
; a bad block check, so putting the code here will catch all
; possible cases.)
;
lda gTrack
cmp #$22
clc
bne @donotskip
lda #TRUE
sta gAdventureInternational
lda gIsProDOS
bne @donotskip
sta gPossibleGamco
@donotskip
rts
;-------------------------------
; IsF7F6
; check for a specific nibble sequence
; ("F7 F6 EF EE AB") that is used by a
; whole-track protection scheme
;
; in slot 6, drive 1 is on track to test
; out C clear if sequence was found
; C set if sequence was not found
;-------------------------------
IsF7F6
lda $C0E9
lda #$00
jsr WAIT
tay
lda #$19
sta nibcount
- jsr ReadNib
cmp #$F7
beq +
@restart iny
bne -
dec nibcount
bne -
sec
beq @driveoff
+ ldx #3
- jsr ReadNib
cmp @f7f6_sequence,x
bne @restart
dex
bpl -
clc
@driveoff
lda $C0E8
rts
@f7f6_sequence
!byte $AB,$EE,$EF,$F6
;-------------------------------
; SetupF7F6SecondRound
;
; Print that we found the F7F6 protection track,
; then restart the scan so we can search every sector
; for the protection code.
; Never returns.
; Exits via RestartScan.
;-------------------------------
SetupF7F6SecondRound
; Mark in the sector map that we should ignore
; this protection track the second time around.
lda checksector+1
sta @a+1
lda checksector+2
sta @a+2
ldy gSector
lda #kSectorIgnore
@a sta $D1D1 ; modifed at runtime
ldx @a+1
bne +
dec @a+2
+ dec @a+1
dey
bpl @a
jsr PrintByID ; print that we found the protection track
!byte s_f7
lda #TRUE
sta gIsF7F6 ; set global to activate expensive patcher
jmp RestartScan
;-------------------------------
; JustTheSameDamnThingOverAndOver
; check if track has 512 repeated nibbles
;
; in slot 6, drive 1 is on track to test
; out C clear if found
; C set otherwise
;-------------------------------
JustTheSameDamnThingOverAndOver
lda $C0E9 ; turn on drive motor, but we assume it's already spun up from previous reads so no waiting
lda #$60
sta tmp
lda #$19
sta unform+1
ldx #$00
;
; Timing-sensitive code! Cycle counts in margin for worst case path
;
@reset clv ; 2
ldy #$00 ; 2
sta @cmp+1 ; 4
@loop lda $C0EC ; 4
bpl @loop ; 2 when not taken
!if RELBASE != $2000 {
!if >@loop != >* {
!serious "branch crosses a page"
}
}
dex ; 2
bne @cmp ; 2 when not taken
dec unform+1 ; 5
beq @notfound ; 2 when not taken
@cmp cmp #$d1 ; 2
bne @reset ; 2 when not taken
iny ; 2
bne @loop ; 2 when not taken (3 when taken)
bvs @found ; 2 when not taken
bit tmp ; 3 (sets overflow flag)
bvs @loop ; 3 (always taken)
@found
clc
!byte $24
@notfound
sec
lda $C0E8
rts
;-------------------------------
; IsUnformatted
; check if track is unformatted by counting
; the number of valid nibbles in a row
;
; in slot 6, drive 1 is on track to test
; out C clear if track is unformatted
; C set if track is formatted
;-------------------------------
IsUnformatted
lda $C0E9 ; turn on drive motor, but we assume it's already spun up from previous reads so no waiting
lda #$00
sta unform
lda #$19
sta unform+1
;
; Timing-sensitive code! Cycle counts in margin for worst case path
;
clc
@reset ldy #$00
@loop ldx $C0EC ; 4
bpl @loop ; 2 when not taken
!if RELBASE != $2000 {
!if >@loop != >* {
!serious "branch crosses a page"
}
}
dec unform ; 5
bne + ; 2 when not taken
dec unform+1 ; 5
beq @unformatted;2 when not taken
+ lda gNIBTable,x; 4
bmi @reset ; 2 when not taken
iny ; 2
bne @loop ; 3 when taken
sec
@unformatted
lda $C0E8
rts
;-------------------------------
; IsWideTrack
; check if this track claims to be the previous track
; in the case of EA, track 6 reads as track 5
; in the case of Accolade, track $22 reads as track $21
;
; in slot 6, drive 1 is on track to test
; out C clear if found wide track
; C set if not found
;-------------------------------
IsWideTrack
lda $2E
clc
adc #1
cmp gTrack
beq +
sec
rts
+ clc
rts
;-------------------------------
; ReadNib
; read a single nibble from S6,D1
;
; in: S6,D1 must be spun up and ready to read
; out: A contains nibble value
;-------------------------------
ReadNib
.x1
- lda $C0EC
bpl -
!if RELBASE != $2000 {
!if >.x1 != >* {
!serious "branch crosses a page"
}
}
rts
;-------------------------------
; Read4x4
; read a 4-4-encoded value from S6,D1
;
; in: S6,D1 must be spun up and ready to read
; out: A contains decoded value
; @tmp clobbered
;-------------------------------
Read4x4
.x2
- lda $C0EC
bpl -
!if RELBASE != $2000 {
!if >.x2 != >* {
!serious "branch crosses a page"
}
}
sec
rol
sta tmp
.x3
- lda $C0EC
bpl -
!if RELBASE != $2000 {
!if >.x3 != >* {
!serious "branch crosses a page"
}
}
and tmp
rts
;-------------------------------
; Unexpected5And3InBaggingArea
; check if track is unexpectedly full of
; 5-and-3-encoded sectors on a disk where
; we expected 6-and-2 encoded sectors
;
; used by e.g. Micrograms as a weak form
; of copy protection to foil COPYA-style
; copying
;
; in slot 6, drive 1 is on track to test
; out C clear if unexpected track found
; C set if not found
;-------------------------------
Unexpected5And3InBaggingArea
lda gIs13Sector
beq @no ; if ID'd as a 13 sector disk, then this is not unexpected
lda $C0E9
lda #$19
sta nibcount
ldx #$0C
ldy #$00
@restart
dey
bne +
dec nibcount
beq @no
+
- lda $C0EC
bpl -
@maybeD5
cmp #$D5
bne @restart
- lda $C0EC
bpl -
cmp #$AA
bne @maybeD5
- lda $C0EC
bpl -
cmp #$B5
bne @maybeD5
dex
bne @restart
clc ; passport-test-suite/Real Math.woz [C=0] matches
!byte $A9
@no sec
lda $C0E8
rts