; 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