mirror of https://github.com/a2-4am/anti-m.git
493 lines
11 KiB
Plaintext
493 lines
11 KiB
Plaintext
; Broderbund & Gebelli tracers
|
|
; written by 4am and qkumba
|
|
;
|
|
; tested on
|
|
; - Bug Attack (Cavalier)
|
|
; - Choplifter (Broderbund)
|
|
; - David's Midnight Magic (Broderbund)
|
|
; - Dueling Digits (Broderbund)
|
|
; - Genetic Drift (Broderbund)
|
|
; - Labyrinth (Broderbund)
|
|
; - Quadrant 6112 (Sensible Software)
|
|
; - Red Alert (Broderbund)
|
|
; - Seafox (Broderbund)
|
|
; - Serpentine (Broderbund)
|
|
; - Sky Blazer (Broderbund)
|
|
; - Space Eggs (Sirius)
|
|
; - Space Quarks (Broderbund)
|
|
; - Star Blazer (Broderbund)
|
|
; - Eggs-It (Gebelli)
|
|
; - High Orbit (Gebelli)
|
|
; - Horizon V (Gebelli)
|
|
; - Lazer Silk (Gebelli)
|
|
; - Neptune (Gebelli)
|
|
; - Phaser Fire (Gebelli)
|
|
; - Russki Duck (Gebelli)
|
|
; - Zenith (Gebelli)
|
|
; - Disk Recovery (Sensible Software)
|
|
; - ABM (MUSE)
|
|
;
|
|
IDBroderbund
|
|
; first stage is just a standard hybrid DOS 3.2/3.3 bootloader
|
|
lda #8
|
|
ldx #1
|
|
ldy #11
|
|
jsr CompareMemory
|
|
!byte $A2,$00 ;LDX #$00
|
|
!byte $BD,$00,$08 ;LDA $0800,X
|
|
!byte $9D,$00,$02 ;STA $0200,X
|
|
!byte $E8 ;INX
|
|
!byte $D0,$F7 ;BNE *-7
|
|
bcs @exit
|
|
|
|
; patch code to regain control after it loads 1 sector into $0300
|
|
lda $837
|
|
cmp #$4C
|
|
clc
|
|
bne @maybeSpaceEggs
|
|
lda #<@BroderbundCallback
|
|
sta $0838
|
|
lda #>@BroderbundCallback
|
|
sta $0839
|
|
bne @exit
|
|
|
|
@maybeSpaceEggs
|
|
lda $842
|
|
sta @jmpdos+1
|
|
lda #<@SpaceEggsCallback
|
|
sta $0842
|
|
lda $843
|
|
sta @jmpdos+2
|
|
lda #>@SpaceEggsCallback
|
|
sta $0843
|
|
|
|
@exit
|
|
rts
|
|
|
|
@BroderbundCallback
|
|
; distinguish between different Broderbund bootloaders
|
|
; by examining decryption routine at $0300
|
|
lda $0301
|
|
cmp #$A2
|
|
bne @maybeDMM
|
|
lda $0302
|
|
cmp #$2E
|
|
bne @runanyway
|
|
lda $0303
|
|
cmp #$9A
|
|
bne @runanyway
|
|
;
|
|
; found Choplifter protection
|
|
;
|
|
; duplicate bootloader from $0300 to $0200 and our callback code to $1700
|
|
; [must preserve Y here]
|
|
ldx #$00
|
|
- lda $0300,x
|
|
sta $0200,x
|
|
lda @copyChoplifter,x
|
|
sta $1700,x
|
|
inx
|
|
bne -
|
|
; patch bootloader so it reads the pristine copy at $0200
|
|
dec $030A
|
|
dec $0310
|
|
dec $0316
|
|
dec $031C
|
|
; patch bootloader to regain control after it decrypts itself into $0100
|
|
lda #$4C
|
|
sta $0325
|
|
lda #<@choplifterCallback
|
|
sta $0326
|
|
lda #>@choplifterCallback
|
|
sta $0327
|
|
@runanyway
|
|
jmp $0301
|
|
|
|
@maybeDMM
|
|
cmp #$8C
|
|
bne @runanyway
|
|
lda $030B
|
|
cmp #$4D
|
|
bne @runanyway
|
|
lda $0323
|
|
cmp #$60
|
|
bne @runanyway
|
|
;
|
|
; found David's Midnight Magic protection
|
|
;
|
|
; duplicate bootloader from $0300 to $1300 and our callback code to $1700
|
|
; [must preserve Y here]
|
|
ldx #$00
|
|
- lda $0300,x
|
|
sta $1300,x
|
|
lda @copyDMM,x
|
|
sta $1700,x
|
|
inx
|
|
bne -
|
|
lda #$13
|
|
sta $030A
|
|
sta $0320
|
|
lda #$4C
|
|
sta $0321
|
|
lda #<@DMMCallback
|
|
sta $0322
|
|
lda #>@DMMCallback
|
|
sta $0323
|
|
jmp $0301
|
|
|
|
@copyChoplifter
|
|
!pseudopc $1700 {
|
|
@choplifterCallback
|
|
; patch bootloader to regain control after it loads 4 sectors into $0400
|
|
lda #$4C
|
|
sta $01FB
|
|
lda #<@choplifterCallback2
|
|
sta $01FC
|
|
lda #>@choplifterCallback2
|
|
sta $01FD
|
|
rts
|
|
|
|
@choplifterCallback2
|
|
; patch bootloader so it doesn't wipe main memory
|
|
lda #$60
|
|
sta $04E2
|
|
; patch bootloader to regain control
|
|
; after it loads title screen and code into $2000+
|
|
lda #$4C
|
|
sta $0498
|
|
lda #<@choplifterCallback3
|
|
sta $0499
|
|
lda #>@choplifterCallback3
|
|
sta $049A
|
|
; restore bytes on stack page that we patched earlier
|
|
; because they're checksummed soon
|
|
lda #$AE
|
|
sta $01FB
|
|
lda #$65
|
|
sta $01FC
|
|
lda #$05
|
|
sta $01FD
|
|
jmp $01FB
|
|
|
|
@choplifterCallback3
|
|
; patch bootloader to bypass ROM check at $6300
|
|
lda #$60
|
|
sta $0421
|
|
jmp $0400
|
|
}
|
|
|
|
@copyDMM
|
|
!pseudopc $1700 {
|
|
@DMMCallback
|
|
; patch bootloader to regain control after it loads 4 sectors into $0400
|
|
lda #$4C
|
|
sta $FD
|
|
lda #<@DMMCallback2
|
|
sta $FE
|
|
lda #>@DMMCallback2
|
|
sta $FF
|
|
rts
|
|
|
|
@DMMCallback2
|
|
; distinguish between two variants here
|
|
; [must preserve A here]
|
|
sta @restore+1
|
|
lda $0406
|
|
cmp #$48
|
|
beq @harderVariant
|
|
; one variant JSRs to a ROM check that exits via JMP $0606
|
|
; on failure, which can be fooled by putting an RTS there
|
|
; e.g. Genetic Drift, Red Alert, or Space Quarks
|
|
;
|
|
; patch bootloader to continue booting after ROM check fails
|
|
lda #$60
|
|
sta $0606
|
|
bne @restore ; always branches
|
|
|
|
@harderVariant
|
|
; this variant has a ROM check that exits via JMP $0606
|
|
; but first uses all of $0400..$7FF as a decryption key
|
|
; e.g. David's Midnight Magic
|
|
;
|
|
; patch bootloader to regain control after loading title page
|
|
lda #$4C
|
|
sta $0461
|
|
lda #<@DMMCallback3
|
|
sta $0462
|
|
lda #>@DMMCallback3
|
|
sta $0463
|
|
@restore lda #$FD ; SMC
|
|
rts
|
|
|
|
@DMMCallback3
|
|
; restore bytes that we patched earlier because they're used
|
|
; as part of a decryption key soon, and patch bootloader to
|
|
; bypass ROM check at $6300 (called from $8B5D)
|
|
; [must preserve A here]
|
|
sta @restore2+1
|
|
lda #$60
|
|
sta $0461
|
|
lda #$00
|
|
sta $0462
|
|
sta $0463
|
|
; distinguish further between variants
|
|
; and disable a secondary protection if present
|
|
lda $8BE3
|
|
cmp #$30
|
|
bne @DMMnewer
|
|
lda #$2C
|
|
sta $8BE2
|
|
bne @restore2
|
|
|
|
@DMMnewer
|
|
lda #$60
|
|
sta $8B5D
|
|
|
|
@restore2
|
|
lda #$FD ; SMC
|
|
rts
|
|
}
|
|
|
|
@SpaceEggsCallback
|
|
lda $33C
|
|
cmp #$AD
|
|
bne @maybeQuadrant
|
|
ldx #<@SpaceEggsCallback2
|
|
ldy #>@SpaceEggsCallback2
|
|
lda $3CC
|
|
cmp #$36
|
|
beq @hookhybrid
|
|
ldx #<@StarThiefCallback
|
|
ldy #>@StarThiefCallback
|
|
cmp #$41
|
|
beq @hookhybrid
|
|
ldx #<@BugAttackCallback
|
|
ldy #>@BugAttackCallback
|
|
cmp #$A1
|
|
beq @hookhybrid
|
|
ldx #<@DOS33Callback
|
|
ldy #>@DOS33Callback
|
|
cmp #$B6
|
|
beq @hookhybrid
|
|
ldx #<@MUSECallback
|
|
ldy #>@MUSECallback
|
|
cmp #$76
|
|
bne @jmpdos
|
|
|
|
@hookhybrid
|
|
lda #$0C
|
|
sta $300 ;Sensible Software page-wraparound fix
|
|
lda #$4C
|
|
sta $33C
|
|
stx $33D
|
|
sty $33E
|
|
@jmpdos
|
|
jmp $301
|
|
|
|
@maybeQuadrant
|
|
cmp #$3B
|
|
bne @jmpdos
|
|
lda #$4C xor $99
|
|
sta $39A
|
|
lda #<@QuadrantCallback xor $99
|
|
sta $39B
|
|
lda #>@QuadrantCallback xor $99
|
|
sta $39C
|
|
jmp $301
|
|
|
|
@SpaceEggsCallback2
|
|
lda $37E0
|
|
cmp #$32
|
|
bne +
|
|
lda #$EA
|
|
sta $3CDC
|
|
sta $3CE0
|
|
sta $3CE1
|
|
sta $3CE7
|
|
sta $3CEB
|
|
sta $3CED
|
|
sta $3CF1
|
|
sta $3CF4
|
|
sta $3CF8
|
|
lda #<@SpaceEggsCallback3x
|
|
sta $3CFE
|
|
lda #>@SpaceEggsCallback3x
|
|
sta $3CFF
|
|
ldy #@SpaceEggsCallback3_e-@SpaceEggsCallback3
|
|
- lda @SpaceEggsCallback3-1,y
|
|
sta $300-1,y
|
|
dey
|
|
bne -
|
|
lda $85FF
|
|
sta @SpaceEggsPatch+1
|
|
beq @skip2a
|
|
inc $3D60
|
|
@skip2a
|
|
+ ldy $371D
|
|
cpy $371F
|
|
bne +
|
|
dey
|
|
bne +
|
|
lda $371E
|
|
ora $3720
|
|
ora $3721
|
|
bne +
|
|
inc $371F ; select drive 2
|
|
+ jmp $3700 ; let it goooo...
|
|
|
|
@SpaceEggsCallback3 !pseudopc $300 {
|
|
@SpaceEggsCallback3x
|
|
jsr $3700
|
|
pla
|
|
pla
|
|
@SpaceEggsPatch
|
|
lda #$00
|
|
beq @skip2b
|
|
inc $5D60
|
|
@skip2b
|
|
jsr $5700
|
|
lda #$EA
|
|
sta $49C3
|
|
sta $49C4
|
|
sta $49C8
|
|
sta $49CB
|
|
sta $49CE
|
|
sta $49D2
|
|
sta $49E3
|
|
sta $49E6
|
|
sta $49ED
|
|
sta $49F1
|
|
sta $49F7
|
|
sta $4928
|
|
sta $4934
|
|
sta $493B
|
|
sta $4949
|
|
sta $494F
|
|
sta $4952
|
|
sta $495A
|
|
sta $495E
|
|
sta $4960
|
|
sta $4969
|
|
sta $496F
|
|
sta $4976
|
|
sta $497A
|
|
sta $497E
|
|
rts
|
|
}
|
|
@SpaceEggsCallback3_e
|
|
|
|
@QuadrantCallback
|
|
lda #$60
|
|
sta $6B3
|
|
;work around emulator bugs
|
|
lda #$00
|
|
sta $733
|
|
sta $73F
|
|
jmp $400
|
|
|
|
@StarThiefCallback
|
|
ldy #@StarThiefCallback2_e-@StarThiefCallback2
|
|
- lda @StarThiefCallback2-1,y
|
|
sta @StarThiefCallback2x-1,y
|
|
dey
|
|
bne -
|
|
lda $85FF
|
|
beq @skip2c
|
|
inc $421C
|
|
@skip2c
|
|
lda #$4C
|
|
sta $42C0
|
|
lda #<@StarThiefCallback2x
|
|
sta $42C1
|
|
lda #>@StarThiefCallback2x
|
|
sta $42C2
|
|
jmp $4200
|
|
|
|
@BugAttackCallback
|
|
ldy #@BugAttackCallback2_e-@BugAttackCallback2
|
|
- lda @BugAttackCallback2-1,y
|
|
sta @BugAttackCallback2x-1,y
|
|
dey
|
|
bne -
|
|
lda #$4C
|
|
sta $A2BB
|
|
lda #$D4
|
|
sta $A2BC
|
|
lda #$A2
|
|
sta $A2BD
|
|
lda #$4C
|
|
sta $A2F6
|
|
lda #<@BugAttackCallback2x
|
|
sta $A2F7
|
|
lda #>@BugAttackCallback2x
|
|
sta $A2F8
|
|
lda $85FF
|
|
beq @skip2d
|
|
inc $A234
|
|
@skip2d
|
|
jmp $A200
|
|
|
|
@DOS33Callback
|
|
lda $85FF
|
|
beq @skip2e
|
|
lda #$BD
|
|
ldx #$5F
|
|
ldy #8
|
|
jsr CompareMemory
|
|
!byte $BD,$8A,$C0 ;LDA $C08A,X
|
|
!byte $B0,$03 ;BCS *+5
|
|
!byte $BD,$8B,$C0 ;LDA $C08B,X
|
|
bcs @notdos33
|
|
inc $BD60
|
|
|
|
@notdos33
|
|
@skip2e
|
|
ldx #$60
|
|
jmp $B700
|
|
|
|
@MUSECallback
|
|
lda $85FF
|
|
beq @skip2f
|
|
lda #$7D
|
|
ldx #$5F
|
|
ldy #8
|
|
jsr CompareMemory
|
|
!byte $BD,$8A,$C0 ;LDA $C08A,X
|
|
!byte $B0,$03 ;BCS *+5
|
|
!byte $BD,$8B,$C0 ;LDA $C08B,X
|
|
bcs @notmuse
|
|
inc $7D60
|
|
|
|
@notmuse
|
|
@skip2f
|
|
ldx #$60
|
|
jmp $7700
|
|
|
|
@StarThiefCallback2 !pseudopc $110 {
|
|
@StarThiefCallback2x
|
|
lda #$4C
|
|
sta $6973
|
|
lda #$D2
|
|
sta $6974
|
|
lda #$68
|
|
sta $6975
|
|
jmp $6801
|
|
}
|
|
@StarThiefCallback2_e
|
|
|
|
@BugAttackCallback2 !pseudopc $110 {
|
|
@BugAttackCallback2x
|
|
lda #$16
|
|
sta $4E06
|
|
lda #$4C
|
|
sta $4A78
|
|
lda #$A4
|
|
sta $4A79
|
|
lda #$49
|
|
sta $4A7A
|
|
lda #$87
|
|
sta $EB5
|
|
jmp $4D36
|
|
}
|
|
@BugAttackCallback2_e
|