passport/src/patchers/optimum.a
2021-06-21 10:33:16 -04:00

361 lines
7.7 KiB
Plaintext

;-------------------------------
; #Optimum
; self-overwriter that restores
; content later from custom sector
; e.g. StickyBear Math
;
; module by qkumba
;-------------------------------
!zone {
lda gIsOptimum
bne .jmpexit1
ldx gTrack
dex
beq .dotrack1
;for each track, search for the redirection code
ldy #15
jsr SearchTrack
!byte $A2,$00 ;LDX #$00
!byte $A0,$00 ;LDY #$00
!byte $BD,WILDCARD,WILDCARD ;LDA $xxxx,X
!byte $E8 ;INX
!byte $85,WILDCARD ;STA $xx
!byte $BD,WILDCARD,WILDCARD ;LDA $xxxx,X
!byte $E8 ;INX
!byte $85 ;STA $xx
bcs .checktrack
tay
adc #BASEPAGE-1
sta .iob1+2
sta .iob2+2
pha
tya
;and disable it
jsr modify1 ; passport-test-suite/Stickybear Math.woz [Z=0] reaches here
!byte $60 ;RTS
pla
;find reference to T01 S0F
;to find page to hold protection data
ldy #6
jsr SearchSector
!byte $01,$60,$01,$00,$01,$0F
bcc .iob1
;if it doesn't exist, fetch address from alternative location
inc .iob1+2
inc .iob2+2
ldx #7
;save for later...
.iob1
lda $D109,X
sta .address+1
.iob2
lda $D108,X
cmp #$a9
bne +
lda #0
+ sta .mergelo+1
.checktrack
lda gTrack
bne .jmpexit1
jmp .dotrack0
.retrycount
!byte $D1
.badread
jsr PrintByID ; say read failure
!byte s_optbad
.jmpexit1
jmp .exit
.dotrack1
lda #3
sta .retrycount
.retry
dec .retrycount
beq .badread
;disable decoding, requires custom handling
+ lda #$4C
sta $B8F6
lda #<.readcallback
sta $B8F7
lda #>.readcallback
sta $B8F8
lda #$2C
sta $BE40
;read T01S0F, remains encoded at $BB00-BC55
jsr ReadSector
;re-enable decoding
lda #$BD
sta $B8F6
lda #$8C
sta $B8F7
lda #$C0
sta $B8F8
lda #$20
sta $BE40
;detect read failure
bcs .retry
;detect write-protect
;work around OE issue
;OE returns nibbles in wrong order on write-protected disks
;versus non-write-protected disks, when reset is issued
;so we detect write-protect and fix the order appropriately
ldx gRWTSParams+1
lda $C08D,x
lda $C08E,x
bpl +
ldx $BB00
ldy #1
- lda $BB00,y
sta $BAFF,y
iny
bne -
ldy #$54
- lda $BC00,y
sta $BC01,y
dey
bpl -
stx $BC00
+
;decode and stash content
lda #$BC
sta .tblsel1+2
sta .tblsel2+2
lda #$88
sta .direction1
sta .direction2
lda #$86
sta $26
ldy #$53
-
.tblsel1
ldx $D100,y
lda .xlattbl-($96+$16),x
asl
asl
asl
asl
.direction1
dey
.tblsel2
ldx $D100,y
.swapbase4
ora .xlattbl-($96+$16),x
sty $2C
ldy $26
sta $300,y
ldy $2C
bne +
dec .tblsel1+2
dec .tblsel2+2
lda #$C8
sta .direction1
sta .direction2
!byte $24 ;mask DEY
+
.direction2
dey
dec $26
ldx $26
inx
bne -
jmp .exit
.readnib
- lda $C08C,x
bpl -
rts
;read protected data
.readcallback
- jsr .readnib
sta $C08D,x
nop
nop
- jsr .readnib
dey
sta $BC00,y
bne -
- jsr .readnib
sta $BB00,y
iny
bne -
clc
rts
.xlattbl
!byte $00,$01,$00,$07,$08,$09,$01,$02
!byte $02,$00,$01,$06,$04,$03,$04,$03
!byte $05,$05,$00,$02,$01,$0A,$07,$0E
!byte $05,$02,$01,$06,$07,$03,$00,$02
!byte $05,$0B,$04,$0F,$00,$07,$0A,$01
!byte $02,$03,$00,$0C,$0C,$06,$07,$05
!byte $08,$06,$02,$04,$01,$00,$08,$0A
!byte $03,$0E,$00,$01,$07,$09,$0A,$05
!byte $0B,$02,$05,$10,$03,$04,$0C,$06
!byte $0D,$01,$0F,$06,$05,$0E,$0F,$0B
!byte $11,$02,$00,$09
;track 0, find the region with replaced page
;for loads to $B1 and $03, the page is stand-alone
;otherwise we have to find which page to merge
;the protection is that $87 bytes of a particular page,
;and which page depends on the title in question,
;are supplied by reading the data from the protected sector
;failing to read the data causes the title to crash
.jmpexit2
jmp .exit
.dotrack0
jsr PrintByID
!byte s_construct
lda .address+1
bmi .domerge
cmp #3
beq .domerge
ldy #8
jsr SearchTrack
!byte $20,$5D,$B6 ;JSR $B65D
!byte $01,$0E ;track 1, sector #$0E
!byte $00,$08,$18 ;address, count
bcs .jmpexit2 ;give up
adc #BASEPAGE
sta .patch1+2
sta .patch2+2
;convert address to track/sector
.address
lda #$D1
sbc #7
pha
and #$0F
sta tmp
lda #$D1
sta .address+1 ; restore default value
.patch1
lda $D104,x
sbc tmp
and #$0F
sta gSector
pla
php
lsr
lsr
lsr
lsr
clc
.patch2
adc $D103,x
tay
plp
bcs +
iny
+ sty gTrack
;read replaced page
.domerge
lda #$21 ; $2100-21FF
sta gAddress+1
jsr ReadSector
lda .mergelo+1
beq ++
dec gSector
bpl +
lda #$0F
sta gSector
dec gTrack
+ inc gAddress+1
jsr ReadSector
dec gAddress+1
ldy #0
.mergelo
lda $2100,y ; self-modified
sta $2100,y
iny
bne .mergelo
++
;merge content
ldy #$86
- lda $300,y
sta $2100,y
dey
cpy #$FF
bne -
;read other page in block
;sector $01 pairs with $0F on disk, but
;sector $0E pairs with $0F in RAM disk or image
ldx #1
stx gTrack
lda gHardDiskRef
ora gRAMDiskRef
beq +
ldx #$0E
+ stx gSector
dec gAddress+1 ; and $2000-20FF
jsr ReadSector
;write replaced block
lda #$20 ; $2000-21FF
sta mliparam+3 ; hi byte of data buffer
dec mliparam+4 ; lo byte of block number
jsr SwapProDOS ; ProDOS out -> in
lda gHardDiskRef
ora gRAMDiskRef
bne +
lda #$81 ; 'write block' command
ldy #$03 ; parameter count
jsr mli
bcs .writeerr
bcc .writedone
+ jsr WriteToFile
.writeerr
.writedone
jsr SwapProDOS ; ProDOS in -> out
;restore original disk location
dec gTrack ; #0
lda #$0F
sta gSector
.exit
}