passport/src/patchers/choplifter.a
2021-07-11 11:12:04 -04:00

522 lines
11 KiB
Plaintext

;-------------------------------
; #Choplifter
; insane protection by Roland Gustafsson
; licensed by Broderbund, Gebelli, and others
;
; module by qkumba
;
; tested on
; - Choplifter (Broderbund)
; - Dueling Digits (Broderbund)
; - Eggs-It (Gebelli)
; - High Orbit (Gebelli)
; - Horizon V (Gebelli)
; - Labyrinth (Broderbund)
; - Lazer Silk (Broderbund)
; - Neptune (Gebelli)
; - Phaser Fire (Gebelli)
; - Russki Duck (Gebelli)
; - Seafox (Broderbund)
; - Serpentine (Broderbund)
; - Sky Blazer (Broderbund)
; - Star Blazer (Broderbund)
;-------------------------------
!zone {
Choplifter
lda #$00
sta gCommand ; passport-test-suite/Eggs-It.woz [Z=1] reaches here
sta dct+1
jsr ChangeTrackNW
jsr IncProgress
ldx #$00
- lda .readtracki,x
sta $2000,x
inx
bne -
.read
asl gTrack
jsr ReadChoplifter
lsr gTrack
jsr WriteTrackNA
ldx gTrack
inx
txa
pha
jsr ChangeTrackNW
jsr IncProgress
pla
cmp #$23
bne .read
bit gMode ; done if in verify-only mode
bpl .exit
; start with RDOS as a minimal SD base
; and copy SD code for free
ldx #ID_RDOS13
jsr ConstructStandardDelivery
ldx #$B0
stx $104E ; exit address
stx $1050 ; next-stage addressing
inx
stx $104F ; next-stage addressing
inx
stx $105D ; next-stage addressing
lda #$10
sta modsrc+1
lda #$5E
sta modsrc
ldx #$27
lda #$67
jsr .inittable
lda #$1F
sta modsrc+1
lda #$00
sta modsrc
ldx #$87
lda #$C7
jsr .inittable
dec modsrc+1
ldx #$0F
lda #$27
jsr .inittable
ldx #$47
lda #$87
jsr .inittable2
dec $1E00
lda #$C0
sta $10DD
sta $1EAF
sta $1F7F
ldy #0
- lda .stage2,y
sta $1D00,y
iny
cpy #.exit2-.stage2
bne -
jsr PrintByID
!byte s_bootwrite
lda #$00
sta gTrack
jsr WriteTrackNA
inc gPatchCount
.exit
jsr .cleanup
jmp Pass
.cleanup
lda $C0E8
lda #$01
sta gCommand
sta dct+1
rts
ReadChoplifter
lda #BASEPAGE
sta modsrc+1
lda #$00
sta modsrc
- jsr ReadSector ; really just seek
lda $C0E9 ; turn the drive back on
; no need for spin-up because we are fast enough
ldx #$04
lda gTrack
beq .settrack00
cmp #$12
bcc .settrack01
cmp #$16
bcc .ignore
beq .readtrack0B
cmp #$3E
bcs .checktrack1E
jsr .readtrack
inc gTrack
lda gTrack
lsr
bcs -
dec gTrack
.ignore
rts
.cancel
jsr .cleanup
jmp Cancel
.settrack00
lda #$D5
sta cmp1+1
sta cmp2+1
lda #$DD
sta cmp1+0
sta cmp2+0
!byte $2C
.settrack01
ldx #$08
.readtrack
stx tmpx
jsr $2000 ; must run from page-aligned address for precise timing
;back-up in case of read failure
lda unform+0 ; prologue 2
sta cmp2+0
lda unform+1 ; prologue 1
sta cmp2+1
lda prbuf+0 ; epilog
sta cmp1+0
lda prbuf+1 ; prologue 3
sta cmp1+1
lda moddest+1
sta modsrc+1
rts
.readtrack0B
.checkkey1
lda KEY
bmi .cancel
jsr ReadNib
- cmp #$DD
bne .checkkey1
jsr ReadNib
cmp #$F5
bne -
jsr ReadNib
cmp #$D5
bne - ; this had the same bug (see below)
ldx #$03
- jsr Read4x4
jsr Read4x4
jsr Read4x4
sta cmp1+0,x
dex
bpl -
rts
.checktrack1E
cmp #$40
bcs .checktrack20
rts
.checktrack20
beq .readtrack20
cmp #$44
beq .readtrack22
rts
.readtrack20
ldx #1
jsr .readtrack
lda (BASEPAGE<<8)+$C5
sta .readtrack20i+.prolog1+1-.reloc
lda (BASEPAGE<<8)+$CC
sta .readtrack20i+.prolog2+1-.reloc
lda (BASEPAGE<<8)+$D3
sta .readtrack20i+.prolog3+1-.reloc
ldy #$00
- lda .readtrack20i,y
sta $2100,y
iny
bne -
ldx #$60
jmp $2100 ; must run from page-aligned address for precise timing
.readtrack20i !pseudopc $2100 {
.reloc
-- jsr .readnibx
.prolog1
- cmp #$D1 ; SMC
bne --
jsr .readnibx
.prolog2
cmp #$D1 ; SMC
bne -
jsr .readnibx
.prolog3
cmp #$D1 ; SMC
bne - ; this had the same bug
.x1
-- lda $C0EC ; timing issue requires unrolling part of this
bpl --
!if >.x1 != >* {
!serious "branch crosses a page"
}
sec
rol
sta tmp
jsr .readnibx
and tmp
sta (BASEPAGE+8)<<8,y
iny
jsr .read4x4x
sta (BASEPAGE+8)<<8,y
iny
jsr .readnibx
sec
rol
sta tmp
.x2
- lda $C0EC
bpl -
!if >.x2 != >* {
!serious "branch crosses a page"
}
and tmp
sta (BASEPAGE+8)<<8,y
iny
cmp #$EA
bne --
rts
.read4x4x
- lda $C08C,x
bpl -
sec
rol
sta tmp
- lda $C08C,x
bpl -
and tmp
rts
}
.readtrack22
ldx #$40
ldy #$00
-- dey
bne +
dex
beq ++
+ ldx #$60
jsr .readnibx
- cmp #$D5
bne --
jsr .readnibx
cmp #$FF
bne -
jsr .readnibx
cmp #$DD
bne - ; this had the same bug
ldy #$00
- jsr .read4x4x
sta BASEPAGE<<8,y
iny
bne -
++ rts
.readtracki !pseudopc $2000 {
ldx #$60
lda #$E0
sta tmpa
sta tmpy
.retry
lda tmpx
sta nibcount
lda modsrc
sta moddest
lda modsrc+1
sta moddest+1
ldy #$00
--- inc tmpa
beq .inc_tmpy
jsr .readnibx
-- cmp cmp2+1
bne ---
jsr .readnibx
- cmp cmp2+0
bne --
jsr .readnibx
cmp cmp1+1
bne - ; this has a bug which is also present in the original code
; it branches to the middle nibble instead of the first one
; it allows PR0 PR1 [any] PR1 PR2 instead of requiring PR0 PR1 PR2
-- lda $C08C,x
bpl --
rol
sta tmp
- lda $C08C,x
bpl -
and tmp
sta (moddest), y
iny
bne --
asl $C000
- lda $C08C,x
bpl -
cmp cmp1+0
bne .retry
inc moddest+1
dec nibcount
bne --
jsr .readnibx
sta prbuf+1 ; prologue 3
jsr .readnibx
sta unform+0 ; prologue 2
jsr .readnibx
sta unform+1 ; prologue 1
jsr .readnibx
sta prbuf+0 ; epilog
jsr .readnibx
cmp unform+1 ; trailer epilog
bne .retry
rts
.inc_tmpy
inc tmpy
bne ---
;;something
jsr .cleanup
jmp FatalError
.readnibx
- lda $C08C,x
bpl -
rts
}
.inittable
ldy #$08
.inittable2
sta tmp
.buildtable
txa
sta (modsrc),y
dex
iny
tya
and #$0F
cmp #$0F
bne .buildtable
tya
sbc #$0F
tay
txa
sta (modsrc),y
tya
adc #$18-1 ; carry set by sbc
tay
txa
adc #$0F
tax
cmp tmp
bne .buildtable
rts
.stage2 !pseudopc $B000 { ; high address that won't be hit on the first round of SD
lda $c057
lda $c054
lda $c052
lda $c050
ldx #0
- lda $800,x
sta $B300,x
inx
bne -
ldx #$42
txs
lda #>(.resume-1)
pha
lda #<(.resume-1)
pha
jmp $4000
.resume
ldx #0
- lda .stager,x
sta $500,x
lda (*+$ff) and $ff00,x
sta $200,x
lda (*+$1ff) and $ff00,x
sta $400,x
lda $B300,x
sta $800,x
txs
inx
bne -
jsr .dostep4
ldy #2 ; pagehi, first table
sty $807
ldy #$60 ; rts
sty $84c
ldx $2b ; SD requires X=boot slot x16
jsr .callSD ; including original $8xx to $7xx
asl $807 ; 4xx, second table
jmp $500
.stager !pseudopc $500 {
jsr .callSD
jsr .step
lda #$60 ; rts
sta $801
; to enable writing requires finding three spare pages
; that is common to all games. I did not succeed.
; for that reason, auto-crack is read-only.
sta $207
lda #6
sta $27
jsr $823 ; read patch table to $600
jsr .dostep2 ; reach track $22
sta $3d
lda #4
sta $27
jsr $823 ; read high scores to $400
lda $C088,x
ldy #0 ; avoid CFFA bug (Y is not zero on return)
- lda $700,y
sta $800,y
iny
bne -
- lda $600,y
sta .patcher+1
lda $601,y
sta .patcher+2
lda $602,y
iny
iny
iny
.patcher
sta $d1d1
cmp #$ea
bne -
jmp ($20)
.callSD
sta $806 ; pagelo
ldy #$ff
jsr $805
beq .step
.dostep4
jsr .dostep2
.dostep2
jsr .step
.step
jsr $82F
lsr $40
rts
} ;$5xx
} ;$Bxxx
.exit2
}