passport/src/analyze.a

467 lines
13 KiB
Plaintext
Raw Normal View History

;-------------------------------
; SkipTrack
; out: C clear if we should skip this track
; C set if we should not skip this track
;-------------------------------
!zone {
SkipTrack
; don't look for whole-track protections on track 0, that's silly
lda gTrack
2019-04-16 05:39:12 +00:00
sec
beq .linknoskip
;
; Electronic Arts protection track?
;
jsr IsEATrack6
lda #s_eatrk6
bcc .print
;
; Nibble count track?
;
jsr JustTheSameDamnThingOverAndOver
lda #s_sync
bcc .print ; always branches
;
; Unformatted track?
;
jsr IsUnformatted
2019-04-16 05:39:12 +00:00
.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
jmp SetupF7F6SecondRound
.print
jsr PrintByID
;
; 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
2019-04-16 05:39:12 +00:00
clc
bne .donotskip
lda gIsProDOS
2019-04-16 05:39:12 +00:00
bne .donotskip
sta gPossibleGamco
.donotskip
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; IsF7F6
2017-01-08 03:35:35 +00:00
; 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
;-------------------------------
!zone {
IsF7F6
2017-01-08 03:35:35 +00:00
lda $C0E9
lda #$00
jsr WAIT
2019-04-16 05:39:12 +00:00
tay
lda #$19
2017-01-08 03:35:35 +00:00
sta nibcount
2019-04-21 01:51:09 +00:00
- jsr .readnib
2017-01-08 03:35:35 +00:00
cmp #$F7
beq +
.restart iny
2017-01-08 03:35:35 +00:00
bne -
dec nibcount
bne -
2019-04-16 05:39:12 +00:00
sec
beq .driveoff
+
2019-04-16 05:39:12 +00:00
jsr .readnib
2017-01-08 03:35:35 +00:00
cmp #$F6
bne .restart
2019-04-16 05:39:12 +00:00
jsr .readnib
2017-01-08 03:35:35 +00:00
cmp #$EF
bne .restart
2019-04-16 05:39:12 +00:00
jsr .readnib
2017-01-08 03:35:35 +00:00
cmp #$EE
bne .restart
2019-04-16 05:39:12 +00:00
jsr .readnib
2017-01-08 03:35:35 +00:00
cmp #$AB
bne .restart
2017-01-08 03:35:35 +00:00
clc
2019-04-16 05:39:12 +00:00
.driveoff
lda $C0E8
rts
2019-04-16 05:39:12 +00:00
.readnib
- lda $C0EC
bpl -
rts
}
;-------------------------------
; 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
dec .a+1
bne +
dec .a+2
+ dey
bpl .a
; print that we found the protection track
lda #s_f7
jsr PrintByID
; set global to activate expensive patcher
lda #TRUE
sta gIsF7F6
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
;-------------------------------
!zone {
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
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
2017-01-08 03:35:35 +00:00
lda $C0E8
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; IsUnformatted
; check if track is unformatted by counting
; the number of valid nibbles in a row
2017-01-08 03:35:35 +00:00
;
; in slot 6, drive 1 is on track to test
; out C clear if track is unformatted
; C set if track is formatted
;-------------------------------
!zone {
2017-01-08 03:35:35 +00:00
IsUnformatted
lda #$FD
sta gNIBTableFF
lda $C0E9 ; turn on drive motor, but we assume it's already spun up from previous reads so no waiting
2017-01-08 03:35:35 +00:00
lda #$00
sta unform
lda #$19
2017-01-08 03:35:35 +00:00
sta unform+1
;
; Timing-sensitive code! Cycle counts in margin for worst case path
;
.reset ldy #$00
.loop ldx $C0EC ; 4
bpl .loop ; 2 when not taken
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
!byte $24
.unformatted
clc
2017-01-08 03:35:35 +00:00
lda $C0E8
lda #$3F
sta gNIBTableFF
2017-01-08 03:35:35 +00:00
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; 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 {
2017-01-08 03:35:35 +00:00
xHeredityDog
lda $08FE
clc
adc #$04
ldx #$16
ldy #$4A
2017-01-08 03:35:35 +00:00
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
2017-01-08 03:35:35 +00:00
!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
2017-01-08 03:35:35 +00:00
sta T00S0A
.exit
2017-01-08 03:35:35 +00:00
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; 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 {
2017-01-08 03:35:35 +00:00
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
2017-01-08 03:35:35 +00:00
sta T11S0F
.no
2017-01-08 03:35:35 +00:00
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; 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 {
2017-01-08 03:35:35 +00:00
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
2017-01-08 03:35:35 +00:00
sta T01S0F
.no
2017-01-08 03:35:35 +00:00
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; 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)
2017-01-08 03:35:35 +00:00
;
; in: $0800..$08FF contains boot0
; either $3600..$3FFF or $B600..$BFFF contains boot1
2017-01-08 03:35:35 +00:00
; out: C clear if RWTS was modified in this routine
; C set otherwise
;-------------------------------
!zone {
2017-01-08 03:35:35 +00:00
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
2019-04-16 05:39:12 +00:00
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
2019-04-16 05:39:12 +00:00
;;ldy #$00 ; sector
.all
stx gTrack
sty gSector
2017-01-08 03:35:35 +00:00
lda #$00
sta gAddress
lda #$0C
adc #BASEPAGE
sta gAddress+1
jsr ReadSector ; read sector so we can look for 'JMP $B4BB' marker
2017-01-08 03:35:35 +00:00
bcs _b4bbexit
lda #$0C
ldx #$84
ldy #$03
jsr compare
!byte $4C,$BB,$B4
bcs _b4bbexit
ldx #$02 ; track
ldy #$02 ; sector
2019-04-16 05:39:12 +00:00
lda gIsDOS32
bne .allb
.dos32b
ldy #$09 ; sector
.allb
stx gTrack
sty gSector
jsr ReadSector ; read sector to get address prologue 3 for rest of disk
2017-01-08 03:35:35 +00:00
bcs _b4bbexit
lda #$0C
adc #BASEPAGE
sta x0+2
x0 lda $FFC2 ; high byte modified at runtime (above)
2017-01-08 03:35:35 +00:00
b4bbmodify
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
2017-01-08 03:35:35 +00:00
lda #$DE
b4bbmodify2
sta $FFFF ; modified at runtime (high byte in Inspect1, low byte above)
lda gIsDOS32
bne _b4bbexit
lda #kSectorCustomDOS32B4BB
sta T02S0C
2017-01-08 03:35:35 +00:00
_b4bbexit
pla
sta gSector
pla
sta gTrack
rts
}
2017-01-08 03:35:35 +00:00
;-------------------------------
; 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 {
2017-01-08 03:35:35 +00:00
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
2017-01-08 03:35:35 +00:00
!byte $EA,$EA,$EA,$EA,$BD,$8C,$C0,$2A
!byte $30,$02
bcs .no
.yes
lda #kSectorSwitchToBuiltinRWTS
2017-01-08 03:35:35 +00:00
sta T00S09
.no
2017-01-08 03:35:35 +00:00
rts
}
2017-01-30 22:10:41 +00:00
;-------------------------------
; IsEATrack6
; check if track 6 even exists
; in the case of EA, track 6 reads as track 5
;
; in slot 6, drive 1 is on track to test
; out C clear if read track does not match expected track
; C set otherwise
;-------------------------------
IsEATrack6
lda gTrack
cmp #6
sec
bne +
lda $2E ;DOS read track number
sbc #5
cmp #1
+ rts