passport/src/patchers/holle.a

278 lines
7.2 KiB
Plaintext

;-------------------------------
; #HOLLE
; encrypted bootloader hides an evil RWTS
;
; tested on
; - Bats in the Belfry (Phoenix Software)
; - Bouncing Kamungas (Penguin Software)
; - Crime Wave (Penguin Software)
; - Mad Rat (Phoenix Software)
; - Masquerade (Phoenix Software)
; - Pensate (Penguin Software)
; - Sherwood Forest (Phoenix Software)
; - Thunder Bombs (Penguin Software)
; - The Spy Strikes Back (Penguin Software)
;-------------------------------
!zone {
lda gIsHolle
beq +
jmp .exit
+ lda gTrack
bne +
jmp .DecryptBootloader
+
lda #$0F
sta .sector+1
.sector lda #$FD
ldx #$8B
ldy #$06
jsr compare ; first data epilogue nibble
- LDA $C08C,X
BPL -
!byte $C9
bcs +
ldx #$91
jsr compare1
!byte $DE
bcc +
jsr modify1
!byte $DE
+
ldx #$2F
ldy #$06
jsr compare ; first address epilogue nibble
- LDA $C08C,X
BPL -
!byte $C9
bcs +
ldx #$35
jsr compare1
!byte $DE
bcc +
jsr modify1
!byte $DE
+
ldx #$9D
ldy #$05
jsr compare
!byte $A9,WILDCARD
JSR $B8B8
bcs +
ldx #$9E
jsr compare1 ; first data epilogue nibble (write)
!byte $DE
bcc +
jsr modify1
!byte $DE
+
dec .sector+1
bpl .sector
; look for secondary RWTS that enforces elongated timing after data prologue
; e.g. Sherwood Forest
ldy #$09
jsr SearchTrack
!byte $49,$AD ; EOR #$AD
!byte $D0,$E7 ; BNE -
!byte $08 ; PHP
!byte $20,WILDCARD,WILDCARD ; JSR xxxx
!byte $28 ; PLP
bcs +
jsr inx4
jsr modify2
!byte $F0,$03 ; BEQ +3
; look for secondary disk volume number check
; e.g. Sherwood Forest
+ ldy #$03
jsr SearchTrack
!byte $A4,$1A ; LDY $1A
!byte $8C ; STY
bcs +
jsr modify2
!byte $A0,$00 ; LDY #$00
; look for save game disk volume number check
; e.g. Sherwood Forest
+ ldy #$05
jsr SearchTrack
!byte $AD,$16,$98 ; LDA $9816
!byte $F0,$0F ; BEQ +0F
bcs +
jsr inx4
jsr modify1
!byte $00
; look for secondary disk volume number check
; e.g. Crime Wave
+ ldy #$04
jsr SearchTrack
LDA $2F
ORA $2E
bcs + ; passport-test-suite/Crime Wave.woz [C=0] matches
ldy #$04
jsr modify
LDA #$00
STA $2F
+ jmp .exit
.DecryptBootloader ; we've read the entire disk, now we're on track 0
jsr ReorderBuffer
ldy #(.decrypt1End-.decrypt1Start)
jsr SearchTrack; find decryption loop #1
.decrypt1Start
LDX #WILDCARD
- EOR $082D,X
STA $0110,X
DEX
BPL -
.decrypt1End
bcs .PatchBootloader
clc ; set up a decryption loop to simulate this one
adc #BASEPAGE
sta .decrypt1+2
sta .decrypt1_eor+2
inx
stx .decrypt1+1
inx
stx .decrypt1_eor+1
ldy #(.decrypt2End-.decrypt2Start)
jsr SearchTrack; find decryption loop #2
.decrypt2Start
LDX $082B
- EOR $0900,X
STA $0500,X
INX
BNE -
.decrypt2End
bcs .PatchBootloader
clc ; set up a decryption loop to simulate this one
adc #BASEPAGE
sta .decrypt2_load+2
sta .decrypt2_store+2
sta .decrypt2_eor+2
inx
inx
inx
stx .decrypt2_eor+1
lda #BASEPAGE
sta .decrypt1_load+2
sta .decrypt1_store+2
sta .decrypt2+2
jsr PrintByID
!byte s_decryptrwts
inc gPatchCount
lda #$4C
.decrypt1
ldx $FDFD ; simulate the decryption within the track buffer
.decrypt1_load
- eor $FD2D,x
.decrypt1_store
sta $FD2D,x
dex
bpl -
ldy #$03
.decrypt2
ldx $FD2B
.decrypt2_load
- eor $FD00,x
.decrypt2_store
sta $FD00,x
inx
bne -
inc .decrypt2_load+2
inc .decrypt2_store+2
dey
bne -
lda #$BD ; LDA abs,X opcode
.decrypt1_eor
sta $FDFD ; EOR -> LDA so now decryption loop #1 is just a copy loop
.decrypt2_eor
sta $FDFD ; EOR -> LDA so now decryption loop #2 is just a copy loop
.PatchBootloader
jsr ReorderBuffer
ldy #(.addressEpilogueEnd-.addressEpilogueStart)
jsr SearchTrack
.addressEpilogueStart
!byte $C9,WILDCARD
BNE +
CLC
RTS
+ SEC
RTS
.addressEpilogueEnd
bcs +
inx
jsr modify1 ; normalize address epilogue 1st nibble
!byte $DE
+
ldy #(.dataPrologue3End-.dataPrologue3Start)
jsr SearchTrack
.dataPrologue3Start
EOR #$AD
!byte $D0,$E7
PHP
!byte $20
.dataPrologue3End
bcs +
inx
inx
inx
inx
jsr modify2 ; disable CPU-burning JSR after data prologue
!byte $F0,$03
+
ldy #(.dataEpilogue1End-.dataEpilogue1Start)
jsr SearchTrack
.dataEpilogue1Start
!byte $C9,WILDCARD
!byte $D0,$9B
NOP
.dataEpilogue1End
bcs +
inx
jsr modify1 ; normalize data epilogue 1st nibble
!byte $DE
+
ldy #(.dataEpilogue3End-.dataEpilogue3Start)
jsr SearchTrack
.dataEpilogue3Start
!byte $EB
!byte $D0,$86
.dataEpilogue3End
bcs +
inx
inx
jsr modify1 ; ignore data epilogue 3rd nibble
!byte $00
+
ldy #(.diskVolumeEnd-.diskVolumeStart)
jsr SearchTrack
.diskVolumeStart
LDY $2F
.diskVolumeEnd
bcs +
jsr modify2 ; don't use disk volume number to initialize data field checksum
LDY #$00
+
ldy #(.alternatingTrackEnd-.alternatingTrackStart)
jsr SearchTrack
.alternatingTrackStart
EOR $01
AND #$01
.alternatingTrackEnd
bcs .exit
jsr modify1
!byte $A9 ; EOR -> LDA so alternating track check always passes
jmp .exit
.reorderAndExit
jsr ReorderBuffer
.exit
}