Attached Files |
-
AlienBreed.asm (25,129 bytes) 2022-12-25 11:50
***************************************************************************
* / *
* _____.__ _ .___. *
* / /_____________. _________.__________.________ | |________ *
* ___/____ / ____|_/ | /| \| ._ / *
* \ \/ \ \ \ / | :___/¯| \ \ |/ / *
* \_____________\___/_____/___/_____|____| |____|\_____________/ *
* -========================/===========|______\================- *
* *
* .---.----(*( ALIEN BREED WHDLOAD SLAVE )*)---.---. *
* `-./ \.-' *
* *
* (c)oded by StingRay *
* -------------------- *
* July 2018 *
* *
* *
***************************************************************************
***********************************
*** History ***
***********************************
; 25-Jul-2018 - music wasn't replayed properly in main menu, reason was a
; wrong interrupt fix, main interrupt code must be called at
; the end of the VBI in main menu
; - CUSTOM3 can be used to run the "1MB Required" part, thanks
; to Bored Seal for the idea :)
; 24-Jul-2018 - help screen removed for now!
; - patch is finished for now
; 22-Jul-2018 - added "help screen" to display in-game keys when help
; has been pressed, not sure it'll stay though as I didn't
; find a 100% reliable solution for the screen memory yet
; 21-Jul-2018 - fixed the problem with opening/closing map screen with
; joypad, rawkey is now cleared each VBI before reading
; the joypad buttons, seems to work reliable
; 20-Jul-2018 - proper pause handling now when using joypad
; - access fault fix fixed :) no more refresh bugs
; 19-Jul-2018 - Joypad routine now uses actual bits instead of bit numbers
; so checking if 2 or more button have been pressed
; simultaneously is possible, logic adapted (and -> eor)
; 18-Jul-2018 - rewritten joypad reading code fixed :)
; - joypad code works properly now
; - joypad base code optimised a bit
; 17-Jul-2018 - a few problems regarding joypad emulation fixed
; - Joypad reading code rewritten, also not tested yet
; 16-Jul-2018 - some more in-game keys added
; - quit key works in main menu now too
; - default quitkey changed back to F10
; - end picture patched, game can be quit using either mouse/
; joystick buttons or using quitkey
; - main menu patched, VBI fixed, SMC fixed, high-score
; load/save added
; - added JOTD's Joypad reading code, it needs to be enabled
; with CUSTOM2 and is untested so far
; 15-Jul-2018 - Intex computer patched, annoying "efford" typo fixed,
; start with max. money and unlimited money trainers now
; implemented, cache flush after relocating embedded exe
; in Intex Computer exe added
; - start with all weapons and map trainer added
; 14-Jul-2018 - interrupts fixed
; - ButtonWait support for mission texts
; - 68000 quitkey support for main game
; - lots of trainer options added
; - Reset (GURU TIME cheat) patched to quit back to DOS
; 13-Jul-2018 - decryption for title part fixed, no more crash in snoop
; a Friday :) mode
; - started to patch main game, starts now but needs more
; fixes
; - Bplcon0 color bit fixes, long writes to $dff100 fixed,
; access faults fixed
; 12-Jul-2018 - generic decrypter for all encrypted files coded
; 11-Jul-2018 - work started
INCDIR SOURCES:INCLUDE/
INCLUDE WHDLoad.i
OUTPUT AlienBreed.slave
FLAGS = WHDLF_NoError|WHDLF_EmulTrap|WHDLF_ClearMem|WHDLF_NoKbd
QUITKEY = $59 ; F10
;DEBUG
; absolute skip
PL_SA MACRO
PL_S \1,\2-(\1)
ENDM
; jsr+absolute skip
PL_PSA MACRO
PL_PS \1,\2 ; could use PSS here but it fills memory
PL_S \1+6,\3-(\1+6) ; with NOPS so we use standard skip
ENDM
HEADER SLAVE_HEADER ; ws_security + ws_ID
dc.w 17 ; ws_version
dc.w FLAGS ; flags
dc.l 524288 ; ws_BaseMemSize
dc.l 0 ; ws_ExecInstall
dc.w Patch-HEADER ; ws_GameLoader
IFD DEBUG
dc.w .dir-HEADER ; ws_CurrentDir
ELSE
dc.w 0 ; ws_CurrentDir
ENDC
dc.w 0 ; ws_DontCache
dc.b 0 ; ws_KeyDebug
dc.b QUITKEY ; ws_KeyExit
dc.l $80000 ; ws_ExpMem
dc.w .name-HEADER ; ws_name
dc.w .copy-HEADER ; ws_copy
dc.w .info-HEADER ; ws_info
; v16
dc.w 0 ; ws_kickname
dc.l 0 ; ws_kicksize
dc.w 0 ; ws_kickcrc
; v17
dc.w .config-HEADER ; ws_config
.config dc.b "BW;"
dc.b "C2:B:Enable Joypad Support;"
dc.b "C3:B:Enable ""No Extra Memory Found"" Part;"
dc.b "C1:X:Unlimited Lives:0;"
dc.b "C1:X:Unlimited Energy:1;"
dc.b "C1:X:Unlimited Ammo:2;"
dc.b "C1:X:Unlimited Keys:3;"
dc.b "C1:X:Unlimited Money:4;"
dc.b "C1:X:Start with max. Money:5;"
dc.b "C1:X:Start with max. Keys:6;"
dc.b "C1:X:Start with all Weapons and Map:7;"
dc.b "C1:X:No collision between human players:8;"
dc.b "C1:X:In-Game Keys:9;"
dc.b "C1:X:Strafe Mode when hold fire:10;"
dc.b 0
.dir IFD DEBUG
dc.b "data",0
ENDC
.name dc.b "Alien Breed",0
.copy dc.b "1991 Team 17",0
.info dc.b "By Mr.Larmer/JOTD (until V2.2), StingRay/[S]carab^Scoopex (V2.3)",-1
dc.b "V2.3c patch by ztronzo for no collision and strafe",-1
IFD DEBUG
dc.b "DEBUG!!! "
ENDC
dc.b "Version 2.3c (23.12.2020)",0
HighName dc.b "AlienBreed.high",0
CNOP 0,2
TAGLIST dc.l WHDLTAG_ATTNFLAGS_GET
CPUFLAGS dc.l 0
dc.l WHDLTAG_CUSTOM1_GET
TRAINEROPTIONS dc.l 0
dc.l WHDLTAG_CUSTOM2_GET
JOYPADSUPPORT dc.l 0
dc.l WHDLTAG_CUSTOM3_GET
NOEXTRAMEMPART dc.l 0
dc.l TAG_END
TR_INGAMEKEYS = 9 ; bit for in-game keys options
resload dc.l 0
IGNORE_JOY_DIRECTIONS
include ReadJoyPad.s
Patch lea resload(pc),a1
move.l a0,(a1)
move.l a0,a2
lea TAGLIST(pc),a0
jsr resload_Control(a2)
; install keyboard irq
bsr SetLev2IRQ
move.l NOEXTRAMEMPART(pc),d0
beq.b .normal
moveq #22,d0
moveq #78,d1
lea $40000,a0
move.l a0,a5
bsr Loader
lea PLNOMEM_PRE(pc),a0
lea $40000,a1
jsr resload_Patch(a2)
jmp $40000
.normal
; load and decrypt title
moveq #100,d0
moveq #80,d1
lea $30000,a0
move.l a0,a5
bsr Loader
move.l #80*512,d0
jsr resload_CRC16(a2)
cmp.w #$f265,d0 ; SPS 998
beq.b .ok
.wrongver
pea (TDREASON_WRONGVER).w
bra.w EXIT
.ok
; patch
lea PLTITLE(pc),a0
move.l a5,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
lea $7fffc,a7
lea $7f800,a0
move.l a0,USP
; store ext. mem ptr
move.l HEADER+ws_ExpMem(pc),d0
; memory is aligned like this in the original but this is
; not necessary
;add.l #$60000,d0
;and.l #$fff80000,d0
move.l d0,$7fffc
; create code at $3f4.w
lea $3f4.w,a0
move.l #$53e2577e,d5
move.l #$4b83c5be,d6
move.l #$000041fa,d7
move.l #$1E1B57A1,d2
move.l #$BB83F582,d3
move.l #$7FFF0F8F,d4
eor.l d2,d5
eor.l d3,d6
eor.l d4,d7
move.l d5,(a0)+
move.l d6,(a0)+
move.l d7,(a0)
move.l d5,$200.w
; set default VBI
pea AckVBI(pc)
move.l (a7)+,$6c.w
; and start game
jmp (a5)
QUIT pea (TDREASON_OK).w
EXIT move.l resload(pc),a2
bsr.b KillSys
jmp resload_Abort(a2)
KillSys move.w #$7fff,$dff09a
bsr WaitRaster
move.w #$7ff,$dff096
move.w #$7fff,$dff09c
rts
AckVBI move.w #1<<4+1<<5+1<<6,$dff09c
move.w #1<<4+1<<5+1<<6,$dff09c
rte
PLNOMEM_PRE
PL_START
PL_P $6f4,.patchNoMem1 ; patch after decrunching
PL_END
.patchNoMem1
lea PLNOMEM1(pc),a0
lea $60000+$20,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
jmp $60020
PLNOMEM1
PL_START
PL_P $ae,.patchNoMem ; now patch the real decrunched part
PL_SA $6c,$70 ; skip pea $40(a4)
PL_W $7a,$4e71 ; disable rts
PL_L $38+2,$60000 ; don't trash decruncher code
PL_END
.patchNoMem
lea PLNOMEM(pc),a0
move.l a4,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
move.w #$7fff,(a5)
move.w #$7fff,4(a5) ; disable DMA, original code
move.w d5,sr ; SR: 0, original code
jmp (a4)
PLNOMEM PL_START
PL_PS $1e,.enableKbd
PL_END
.enableKbd
bsr SetLev2IRQ
move.w #$8380,$96(a6) ; original code, enable DMA
rts
PLTITLE PL_START
PL_P $1606,Loader
PL_P $ab66,AckVBI
PL_ORW $e7c+2,1<<3 ; enable level 2 interrupts
PL_P $2046,.patch_premain ; file 1c_15
PL_END
.patch_premain
lea PLPREMAIN(pc),a0
pea $8000
move.l (a7),a1
move.l resload(pc),a2
jmp resload_Patch(a2)
FlushCache
move.l resload(pc),a0
jsr resload_FlushCache(a0)
movem.l (a7)+,d0-a6 ; original code
rts
PLPREMAIN
PL_START
PL_P $241a,.patchmain
PL_P $253e,FlushCache ; flush cache after relocating
PL_END
; main file has been decrypted and relocated, patch it
.patchmain
movem.l d0-a6,-(a7)
lea PLMAIN(pc),a0
move.l a5,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
; patch copperlists in data section
; data section relocation start is $600
; data section offset in executable is $7ee84
lea PLMAIN_CHIP(pc),a0
lea $600.w,a1
jsr resload_Patch(a2)
; load high scores
lea HighName(pc),a0
move.l a5,a1
add.l #$200bc,a1
jsr resload_GetFileSize(a2)
tst.l d0
beq.b .noHigh
lea HighName(pc),a0
move.l a5,a1
add.l #$200bc,a1
jsr resload_LoadFile(a2)
.noHigh
; install trainers
move.l TRAINEROPTIONS(pc),d0
; unlimited lives
lsr.l #1,d0
bcc.b .noUnlimitedLives
eor.b #$19,$749c(a5) ; subq.w <-> tst.w
.noUnlimitedLives
; unlimited energy
lsr.l #1,d0
bcc.b .noUnlimitedEnergy
move.l #$bcd4,d1 ; player 1
move.w #1,(a5,d1.l)
move.w #1,2(a5,d1.l) ; player 2
.noUnlimitedEnergy
; unlimited ammo
lsr.l #1,d0
bcc.b .noUnlimitedAmmo
move.l #$d950,d1
eor.b #$19,(a5,d1.l) ; subq.w <-> tst.w
.noUnlimitedAmmo
; unlimited keys
lsr.l #1,d0
bcc.b .noUnlimitedKeys
move.w #1,$7b3a(a5)
.noUnlimitedKeys
; unlimited money (done in the PLINTEXCOMPUTER patch list)
lsr.l #1,d0
.noUnlimitedMoney
; start with max. money (done in the PLINTEXCOMPUTER patch list)
lsr.l #1,d0
.noMaxMoney
; start with max. keys
lsr.l #1,d0
bcc.b .noMaxKeys
pea 30000
move.l (a7),$5a5a(a5) ; player 1
move.l (a7)+,$61fa(a5) ; player 2
.noMaxKeys
; start with all weapons and map
lsr.l #1,d0
bcc.b .noAllWeapons
move.w #%11111111,$28a0+2(a5)
;addq.w #1,$794(a5) ; "has map" flag is cleared in init part
move.w #$4e71,$d9c(a5)
.noAllWeapons
; start No collision between human players:8;"
lsr.l #1,d0
bcc.b .skipNoCollision
move.w #$6012,$76C6(a5)
move.w #$6012,$7736(a5)
.skipNoCollision
move.l JOYPADSUPPORT(pc),d0
beq.b .noJoypad
bsr _detect_controller_types
.noJoypad
movem.l (a7)+,d0-a6
.nomain lea $7fc00,a7 ; original code
jmp (a5)
PLMAINMENU
PL_START
PL_PS $2d2,.sethiflag ; set "high score achieved" flag
PL_PS $9e,.savehighscores
PL_PSA $181e,.SaveVBI,$1828 ; don't modify VBI code
PL_P $1834,.RestoreVBI ; restore old VBI
PL_P $18d8,.AckVBI
PL_END
.AckVBI move.l HEADER+ws_ExpMem(pc),-(a7)
add.l #$1644,(a7) ; call main interrupt code
rts
.SaveVBI
move.l a0,-(a7)
lea .oldVBI(pc),a0
move.l $6c.w,(a0)
move.l (a7)+,a0
rts
.RestoreVBI
move.l .oldVBI(pc),$6c.w
rts
.oldVBI dc.l 0
.savehighscores
movem.l d0-a6,-(a7)
lea .hiflag(pc),a0
tst.b (a0)
beq.b .nohigh
sf (a0)
move.l TRAINEROPTIONS(pc),d0 ; no saving if any trainers are used
bne.b .nohigh
lea HighName(pc),a0
move.l HEADER+ws_ExpMem(pc),a1
add.l #$200bc,a1
move.l resload(pc),a2
move.l #$6f4-$654,d0 ; size
jsr resload_SaveFile(a2)
.nohigh
movem.l (a7)+,d0-a6
moveq #8,d0 ; optimised original code
rts
.sethiflag
move.l a0,-(a7)
lea .hiflag(pc),a0
st (a0)
move.l (a7)+,a0
clr.b (a0)+ ; original code
clr.b (a0)+
clr.b (a0)+
rts
.hiflag dc.b 0
dc.b 0
PLINTEXCOMPUTER
PL_START
PL_P $a8a,FlushCache ; there is an exe embedded, flush
; cache after relocating
PL_B $2471+14,"A" ; fix "efford" typo :)
; unlimited money
PL_IFC1X 4
PL_W $be6,$4e71 ; sub.l d1,(a5) -> nop (tools)
PL_W $14d2,$4e71 ; sub.l d0,d1 -> nop (weapons)
PL_ENDIF
PL_END
PLMAIN_CHIP
PL_START
PL_ORW ($83fc2-$7ee84)+2,1<<9 ; set Bplcon0 color bit
PL_ORW ($8457e-$7ee84)+2,1<<9 ; set Bplcon0 color bit
PL_END
PLMAIN PL_START
PL_SA $f4c6,$f4d0 ; skip long write to $dff100
PL_P $239ae,FlushCache ; flush cache after relocating
PL_P $ada6,Loader
PL_PS $f61a,ChangeDisk
;PL_AL $10978+2,4 ; fix access fault
;PL_AL $10982+2,4 ; fix access fault
PL_PS $10904,.fix
PL_PSS $21274,AckLev4,2
PL_PSS $17bc,AckVBI_R,2
PL_PSS $17da,AckCOP_R,2
PL_PS $2004e,.checkkeys
PL_P $be2a,QUIT ; reset ("GURU TIME" cheat) -> quit
PL_PS $e754,.PatchMainMenu
PL_PS $d2a8,.PatchIntexComputer
PL_IFBW
PL_PS $e976,.WaitButtonMissionText
PL_ENDIF
PL_P $cf2,.PatchEnd
; Mr.Larmer patches
PL_PS $a6d6,Protection
; JOTD patches
; ztronzo patches
PL_IFC1X 10
PL_PS $6BC0,.strafe_start
PL_ENDIF
PL_END
.strafe_start
BTST.B #$06,$00bfe001
beq.b .strafe_player2
BTST.B #$07,$00bfe001
beq.b .strafe_player1
MOVE.W D0,$0140(A0)
bra.b .strafe_finish
.strafe_player1
cmp.W #$f00c,$2(A0)
beq.b .strafe_finish
MOVE.W D0,$0140(A0)
.strafe_player2
cmp.W #$f00a,$2(A0)
beq.b .strafe_finish
MOVE.W D0,$0140(A0)
.strafe_finish
MOVE.W D2,D0
rts
.fix move.l (a0)+,d0
bne.b .dest_ok
addq.l #4,d0
.dest_ok
move.l d0,a1
move.w -4(a1),d0
rts
.PatchMainMenu
movem.l d0-a6,-(a7)
lea PLMAINMENU(pc),a0
lea ($a8edc-$7ee84)+$600,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
movem.l (a7)+,d0-a6
move.w #1<<15+1<<3,$dff09a ; enable level 2 interrupts in main menu
rts
.PatchEnd
move.l HEADER+ws_ExpMem(pc),a0
add.l #$20f20,a0
jsr (a0) ; call original routine
move.l #100000*10,d0 ; more than 27 hours should be enough :)
move.l resload(pc),a0
jsr resload_Delay(a0)
bra.w QUIT
.PatchIntexComputer
movem.l d0-a6,-(a7)
move.l a0,a5
lea PLINTEXCOMPUTER(pc),a0
; $600: start of relocated data section
; $a8edc: offset to intex computer executable in binary
; $7ee84: start offset of data section in binary
lea ($a8edc-$7ee84)+$600,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
lea TRAINEROPTIONS(pc),a0
tst.w .moneyset-TRAINEROPTIONS(a0)
bne.b .noMaxMoney
addq.w #1,.moneyset-TRAINEROPTIONS(a0)
move.l (a0),d0
btst #5,d0
beq.b .noMaxMoney
; set 500000 credits
move.l a5,a0
move.l #500000*2*50,(a0)
.noMaxMoney
movem.l (a7)+,d0-a6
jmp ($a8edc-$7ee84)+$600
.moneyset dc.w 0
.WaitButtonMissionText
move.l a0,-(a7)
moveq #10*10,d0 ; 10 seconds
move.l resload(pc),a0
jsr resload_Delay(a0)
move.l (a7)+,a0
moveq #32,d0 ; optimised original code
rts
.pause_status dc.w 0
.checkkeys
bsr.w .getkey
ror.b #$01,d0
not.b d0
cmp.b HEADER+ws_keyexit(pc),d0
beq.w QUIT
; check joypad buttons
move.l JOYPADSUPPORT(pc),d1
beq.b .nojoypad
; clear raw key to avoid problems (f.e. with map screen)
move.l HEADER+ws_ExpMem(pc),a0
add.l #$200ba,a0
clr.b (a0)
move.w d0,-(a7)
bsr ReadJoypad
move.w (a7)+,d0
tst.b d2 ; was a button pressed?
;beq.b .nojoypad
bmi.w QUIT
lea .pause_status(pc),a0
cmp.w #$19,d2
bne.b .noP
tst.b (a0)
beq.b .first_time
moveq #0,d2 ; clear key code -> wait until
bra.b .ok ; button has pressed again
.first_time
st (a0) ; set pause_status flag
bra.b .ok
.noP clr.b (a0)
.ok move.b d2,d0 ; yes, return mapped key
beq.b .nojoypad
lsl.b #$01,d0
not.b d0
rts
.nojoypad
move.l TRAINEROPTIONS(pc),d1
btst #TR_INGAMEKEYS,d1
beq.b .nokeys
move.l HEADER+ws_ExpMem(pc),a5 ; start of executable
lea .TAB(pc),a0
.search movem.w (a0)+,d1/d2
cmp.b d0,d1
bne.b .next
jsr .TAB(pc,d2.w)
bra.b .nokeys
.next tst.w (a0)
bne.b .search
.nokeys
.getkey move.b $bfec01,d0
rts
.TAB dc.w $36,.SkipLevel-.TAB ; n - skip level
dc.w $12,.RefreshEnergy-.TAB ; e - refresh energy
dc.w $27,.MaxKeys-.TAB ; k - get max. keys
dc.w $20,.RefreshAmmo-.TAB ; a - refresh ammo
dc.w $28,.RefreshLives-.TAB ; l - refresh lives
dc.w $25,.GetMap-.TAB ; h - get hand map
dc.w $11,.GetWeapons-.TAB ; w - get all weapons
dc.w 0 ; end of tab
.SkipLevel
move.w #1,$822(a5)
rts
.RefreshEnergy
move.w #$40,$58fa+$150(a5) ; player 1
move.w #$40,$609a+$150(a5) ; player 2
rts
.MaxKeys
move.w #30000,$58fa+$160(a5) ; player 1
move.w #30000,$609a+$160(a5) ; player 2
rts
.RefreshAmmo
move.w #32,$58fa+$15c(a5) ; player 1
move.w #32,$609a+$15c(a5) ; player 2
rts
.RefreshLives
move.w #4,$58fa+$154(a5) ; player 1
move.w #4,$609a+$154(a5) ; player 2
.GetMap move.w #1,$794(a5)
rts
.GetWeapons
move.w #%11111111,d2
move.w d2,$58fa+$192(a5) ; player 1
move.w d2,$609a+$192(a5) ; player 2
rts
; returns result in d2, either mapped rawkey or 0 if no button was pressed
; -1 if quit
ReadJoypad
lea .joy(pc),a0 ; read joystick in port 2 only
move.b controller_joypad_1(pc),d0
beq.b .joy_only
lea .pad(pc),a0 ; read full CD32 pad
.joy_only
jsr (a0)
moveq #0,d2
lea .TAB(pc),a0
.loop move.l joy0_buttons(pc),d0
move.l (a0)+,d1 ; port
beq.b .port0
move.l joy1_buttons(pc),d0
subq.b #1,d1
beq.b .port1
or.l joy0_buttons(pc),d0 ; both ports
.port1
.port0
move.l (a0)+,d1
move.l (a0)+,d3
and.l d1,d0
eor.l d1,d0
bne.b .no_button
move.w d3,d2
.no_button
tst.l (a0) ; check all entries in table
bpl.b .loop
rts
.pad bra.w _read_joysticks_buttons
.joy moveq #1,d0 ; port 1
bsr _read_joystick
lea joy1_buttons(pc),a0
move.l d0,(a0)
rts
; joypad port (0,1,both), joypad button, mapped rawkey
.TAB dc.l 1,JPF_BTN_GRN,$64 ; left alt, change weapons player 1
dc.l 0,JPF_BTN_GRN,$65 ; right alt, change weapons player 2
dc.l 2,JPF_BTN_YEL,$37 ; M, open map
dc.l 2,JPF_BTN_BLU,$40 ; Space, enter intex computer
dc.l 2,JPF_BTN_PLAY,$19 ; P, pause
dc.l 2,JPF_BTN_FORWARD+JPF_BTN_REVERSE,$45 ; ESC
dc.l 2,JPF_BTN_FORWARD+JPF_BTN_REVERSE+JPF_BTN_PLAY,-1 ; quit
dc.l -1 ; end of tab
CNOP 0,2
AckVBI_R
move.w #1<<5,$dff09c
move.w #1<<5,$dff09c
rts
AckCOP_R
move.w #1<<4,$dff09c
move.w #1<<4,$dff09c
rts
AckLev4 move.w #$400,$dff09c
move.w #$400,$dff09c
rts
ChangeDisk
move.l a0,-(a7)
lea DiskNum(pc),a0
move.b #2,(a0)
move.l (a7)+,a0
rts
Protection eor.b #$4E,$458.w ; this code is forgot in cracked version :)
lea Track(pc),a0
moveq #8-1,d0
.copy move.l (a0)+,(a2)+
dbf d0,.copy
; move.l #$77000000,d0
moveq #$77,d0
ror.l #8,d0
move.l #$4449534B,d1
; move.l #$32000000,d2
moveq #$32,d2
ror.l #8,d2
; move.l #$10000000,d3
moveq #$10,d3
ror.l #8,d3
moveq #2,d4
moveq #-1,d6
; move.l #$FFFF,d5
moveq #0,d5
move.w d6,d5
move.l #$55555555,d7
; read track 0_0 from disk 2 with SYNC $8924 to $200 ptr
; and calculated values are left in d0-d7 !
rts
Track
dc.l $8924912A,$AAAA552A,$AAAAAAA4,$A9254449
dc.l $5149112A,$AAAA92AA,$AAAAAAAA,$AAAAAAAA
Loader bsr.b .load
movem.l d0-a6,-(a7)
bsr Decrypt_AB ; decrypt file if necessary
movem.l (a7)+,d0-a6
moveq #0,d0 ; no errors
rts
.load movem.l d0-a6,-(a7)
mulu.w #512,d0
mulu.w #512,d1
move.b DiskNum(pc),d2
move.l resload(pc),a1
jsr resload_DiskLoad(a1)
movem.l (a7)+,d0-a6
rts
DiskNum dc.b 1
dc.b 0
WaitRaster
.wait btst #0,$dff005
beq.b .wait
.wait2 btst #0,$dff005
bne.b .wait2
rts
***********************************
*** Level 2 IRQ ***
***********************************
SetLev2IRQ
pea .int(pc)
move.l (a7)+,$68.w
move.b #1<<7|1<<3,$bfed01 ; enable keyboard interrupts
tst.b $bfed01 ; clear all CIA A interrupts
and.b #~(1<<6),$bfee01 ; set input mode
move.w #1<<3,$dff09c ; clear ports interrupt
move.w #1<<15|1<<14|1<<3,$dff09a ; and enable it
rts
.int movem.l d0-d1/a0-a2,-(a7)
lea $dff000,a0
lea $bfe001,a1
btst #3,$1e+1(a0) ; PORTS irq?
beq.b .end
btst #3,$d00(a1) ; KBD irq?
beq.b .end
moveq #0,d0
move.b $c00(a1),d0
not.b d0
ror.b #$01,d0
or.b #1<<6,$e00(a1) ; set output mode
cmp.b HEADER+ws_keyexit(pc),d0
beq.w QUIT
.nokeys moveq #3-1,d1
.loop move.b $6(a0),d0
.wait cmp.b $6(a0),d0
beq.b .wait
dbf d1,.loop
and.b #~(1<<6),$e00(a1) ; set input mode
.end move.w #1<<3,$9c(a0)
move.w #1<<3,$9c(a0) ; twice to avoid a4k hw bug
movem.l (a7)+,d0-d1/a0-a2
rte
; generic decrypter for all encrypted Alien Breed files
; stingray, 12.07.2018 (13.07.: CLEANCODE added, file 2 decryption fixed)
; code works with full caches
; done for my version of the Alien Breed WHDLoad patch
; if CLEANCODE is set to 1, all encrypted code will be
; cleared with NOP, this way only the real code is left for easy
; disassembling
CLEANCODE = 1 ; 1: clear encryption code with NOPs
; d0.w: start (sector)
; d1.w: length (sectors)
; a0.l: start of encrypted data
Decrypt_AB
move.l a0,a5
mulu.w #512,d1
lea (a0,d1.l),a6 ; a6: end of encrypted file
lea .FTAB(pc),a0
.search movem.w (a0)+,d2/d3 ; start sector, offset to routine
cmp.w d0,d2
beq.b .found
tst.w (a0)
bne.b .search
rts
.found jmp .FTAB(pc,d3.w) ; decrypt file
.FTAB dc.w 2,.file1-.FTAB
dc.w $64,.file2-.FTAB
dc.w $1da,.file3-.FTAB
dc.w $1c5,.file4-.FTAB
dc.w $16,.file5-.FTAB ; no extra memory detected
dc.w 0 ; end of tab
.file1 move.l a6,a0
move.w #$2800/2-1,d0
moveq #-2,d1
.loop0 eor.w d1,-(a0)
rol.w #1,d1
dbf d0,.loop0
lea $826(a5),a4
lea $f9c(a5),a6
bsr.b .decrypt
lea $13e0(a5),a4
lea $2800(a5),a6
bra.b .decrypt
; at offset $6a98 is unused/forgotten code to encrypt the important
; routines
.file2 lea $14(a5),a4
lea $197a(a5),a6
bsr.b .decrypt
lea $19c6(a5),a4
lea $2bd6(a5),a6
bra.b .decrypt
.file3 move.l a5,a4
lea $17f8(a5),a6
bsr.b .decrypt
lea $5d7c(a5),a4
lea $30*512(a5),a6
bra.b .decrypt
.file4 lea $788(a5),a4
bra.b .decrypt
.file5 move.l a5,a4
; a4.l: start of decryption
; a5.l: start of file
; a6.l: end of decryption
.decrypt
.find cmp.w #$41fa,(a4) ; lea xxx(pc),a0
beq.b .start_found
addq.w #2,a4
cmp.l a6,a4
bcs.b .find
rts
.start_found
move.w 4+2(a4),d0 ; loop counter
lea .TAB(pc),a3
.find_opcode
move.w (a3)+,d3 ; offset to check
movem.w (a3)+,d1/d2 ; opcode/routine offset
cmp.w (a4,d3.w),d1
beq.b .instruction_found
tst.w (a3)
bne.b .find_opcode
rts
.instruction_found
move.w 2(a4),a0 ; offset to destination
lea 2(a4,a0.w),a0
lea .TAB(pc,d2.w),a1
jsr (a1) ; call init code
addq.w #2,a1
.decrypt_loop
jsr (a1) ; call decryption code
dbf d0,.decrypt_loop
; search for dbf opcode to find end of decryption loop
.find_end
cmp.w #$51c8,(a4)
beq.b .end_found
IFNE CLEANCODE
move.w #$4e71,(a4)+ ; encryption code -> nop
ELSE ; so real code is left only
addq.w #2,a4
ENDC
cmp.l a6,a4
bcs.b .find_end
rts
.end_found
IFNE CLEANCODE
move.l #$4e714e71,(a4)+ ; disable dbf d0,xxx
ELSE
addq.w #4,a4 ; skip dbf d0,xxx
ENDC
;move.l a4,a2 ; a2: current decryption loop (debug)
bra.b .decrypt
; offset to check, opcode, routine offset
.TAB dc.w 8,$4460,.NegAx-.TAB ; neg.w -(ax)
dc.w 8,$0a60,.EorI-.TAB ; eor.w #xxx,-(ax)
dc.w 8,$0460,.SubI-.TAB ; sub.w #xxx,-(ax)
dc.w 12,$d360,.AddDx-.TAB ; add.w d1,-(ax)
dc.w 8,$4660,.NotAx-.TAB ; not.w -(ax)
dc.w 12,$b360,.EorDx-.TAB ; eor.w d1,-(ax)
dc.w 12,$9360,.SubDx-.TAB ; sub.w d1,-(ax)
dc.w 8,$e6e0,.RorAx-.TAB ; ror.w -(ax)
dc.w 8,$e7e0,.RolAx-.TAB ; rol.w -(ax)
dc.w 8,$0660,.AddI-.TAB ; add.w #xxx,-(ax)
dc.w 8,$4258,.Clr-.TAB ; clr.w (ax)+
dc.w 4,$4298,.Clr-.TAB ; clr.l (ax)+
dc.w 34,$3e20,.Large-.TAB ; move.w -(a0),d7 -> large decryption loop
dc.w 0 ; end of tab
.NegAx bra.b .NegAx_Init
neg.w -(a0)
rts
.NegAx_Init
rts
.NotAx bra.b .NotAx_Init
not.w -(a0)
rts
.NotAx_Init
rts
.RorAx bra.b .RorAx_Init
ror.w -(a0)
rts
.RorAx_Init
rts
.RolAx bra.b .RolAx_Init
rol.w -(a0)
rts
.RolAx_Init
rts
.EorI bra.b .EorI_Init
move.w 8+2(a4),d1
eor.w d1,-(a0)
rts
.EorI_Init
rts
.SubI bra.b .SubI_Init
move.w 8+2(a4),d1
sub.w d1,-(a0)
rts
.SubI_Init
rts
.AddI bra.b .AddI_Init
add.w d1,-(a0)
rts
.AddI_Init
move.w 8+2(a4),d1
rts
.AddDx bra.b .AddDx_Init
add.w d1,-(a0)
rol.w d2,d1
rts
.AddDx_Init
move.w 8+2(a4),d1
moveq #1,d2
cmp.w #$e359,14(a4) ; rol.w #1,d1
beq.b .rol
neg.w d2 ; -> ror.w #1,d1
.rol rts
.EorDx bra.b .EorDx_Init
eor.w d1,-(a0)
rol.w d2,d1
rts
.EorDx_Init
bra.b .AddDx_Init
.SubDx bra.b .SubDx_Init
sub.w d1,-(a0)
rol.w d2,d1
rts
.SubDx_Init
bra.b .AddDx_Init
.Clr bra.b .ClrInit
rts
.ClrInit
moveq #0,d0 ; clear loop counter -> do nothing
; special case: two clr.l (a0)+ instructions without loop
; clr.l (a0)+
; clr.l (a0)+
cmp.w #$4298,6(a4) ; clr.l (a0)+
bne.b .nospecial
move.w #$51c8,4(a4) ; add fake dbf so our "search for end"
; routine will work
.nospecial
rts
.Large bra.b .LargeInit
move.w -(a0),d7
eor.w d1,d7
ror.w d2,d7
rol.w d6,d7
sub.w d5,d7
add.w d6,d7
swap d1
ror.w #4,d7
swap d2
sub.w d2,d7
rol.w #8,d7
eor.w #$C0DE,d7
add.w d2,d7
eor.l d1,d2
sub.w d2,d7
move.w d7,(a0)
sub.l d7,d6
eor.l d7,d5
add.l d7,d5
rts
.LargeInit
move.l 8+2(a4),d1 ; key 1
move.l 14+2(a4),d2 ; key 2
moveq #0,d7
move.l #'L.K.',d6
move.l #'S.B.',d5
rts
-
AlienBreed-2.asm (25,432 bytes) 2022-12-27 10:10
***************************************************************************
* / *
* _____.__ _ .___. *
* / /_____________. _________.__________.________ | |________ *
* ___/____ / ____|_/ | /| \| ._ / *
* \ \/ \ \ \ / | :___/¯| \ \ |/ / *
* \_____________\___/_____/___/_____|____| |____|\_____________/ *
* -========================/===========|______\================- *
* *
* .---.----(*( ALIEN BREED WHDLOAD SLAVE )*)---.---. *
* `-./ \.-' *
* *
* (c)oded by StingRay *
* -------------------- *
* July 2018 *
* *
* *
***************************************************************************
***********************************
*** History ***
***********************************
; 25-Jul-2018 - music wasn't replayed properly in main menu, reason was a
; wrong interrupt fix, main interrupt code must be called at
; the end of the VBI in main menu
; - CUSTOM3 can be used to run the "1MB Required" part, thanks
; to Bored Seal for the idea :)
; 24-Jul-2018 - help screen removed for now!
; - patch is finished for now
; 22-Jul-2018 - added "help screen" to display in-game keys when help
; has been pressed, not sure it'll stay though as I didn't
; find a 100% reliable solution for the screen memory yet
; 21-Jul-2018 - fixed the problem with opening/closing map screen with
; joypad, rawkey is now cleared each VBI before reading
; the joypad buttons, seems to work reliable
; 20-Jul-2018 - proper pause handling now when using joypad
; - access fault fix fixed :) no more refresh bugs
; 19-Jul-2018 - Joypad routine now uses actual bits instead of bit numbers
; so checking if 2 or more button have been pressed
; simultaneously is possible, logic adapted (and -> eor)
; 18-Jul-2018 - rewritten joypad reading code fixed :)
; - joypad code works properly now
; - joypad base code optimised a bit
; 17-Jul-2018 - a few problems regarding joypad emulation fixed
; - Joypad reading code rewritten, also not tested yet
; 16-Jul-2018 - some more in-game keys added
; - quit key works in main menu now too
; - default quitkey changed back to F10
; - end picture patched, game can be quit using either mouse/
; joystick buttons or using quitkey
; - main menu patched, VBI fixed, SMC fixed, high-score
; load/save added
; - added JOTD's Joypad reading code, it needs to be enabled
; with CUSTOM2 and is untested so far
; 15-Jul-2018 - Intex computer patched, annoying "efford" typo fixed,
; start with max. money and unlimited money trainers now
; implemented, cache flush after relocating embedded exe
; in Intex Computer exe added
; - start with all weapons and map trainer added
; 14-Jul-2018 - interrupts fixed
; - ButtonWait support for mission texts
; - 68000 quitkey support for main game
; - lots of trainer options added
; - Reset (GURU TIME cheat) patched to quit back to DOS
; 13-Jul-2018 - decryption for title part fixed, no more crash in snoop
; a Friday :) mode
; - started to patch main game, starts now but needs more
; fixes
; - Bplcon0 color bit fixes, long writes to $dff100 fixed,
; access faults fixed
; 12-Jul-2018 - generic decrypter for all encrypted files coded
; 11-Jul-2018 - work started
INCDIR SOURCES:INCLUDE/
INCLUDE WHDLoad.i
OUTPUT AlienBreed.slave
FLAGS = WHDLF_NoError|WHDLF_EmulTrap|WHDLF_ClearMem|WHDLF_NoKbd
QUITKEY = $59 ; F10
;DEBUG
; absolute skip
PL_SA MACRO
PL_S \1,\2-(\1)
ENDM
; jsr+absolute skip
PL_PSA MACRO
PL_PS \1,\2 ; could use PSS here but it fills memory
PL_S \1+6,\3-(\1+6) ; with NOPS so we use standard skip
ENDM
HEADER SLAVE_HEADER ; ws_security + ws_ID
dc.w 17 ; ws_version
dc.w FLAGS ; flags
dc.l 524288 ; ws_BaseMemSize
dc.l 0 ; ws_ExecInstall
dc.w Patch-HEADER ; ws_GameLoader
IFD DEBUG
dc.w .dir-HEADER ; ws_CurrentDir
ELSE
dc.w 0 ; ws_CurrentDir
ENDC
dc.w 0 ; ws_DontCache
dc.b 0 ; ws_KeyDebug
dc.b QUITKEY ; ws_KeyExit
dc.l $80000 ; ws_ExpMem
dc.w .name-HEADER ; ws_name
dc.w .copy-HEADER ; ws_copy
dc.w .info-HEADER ; ws_info
; v16
dc.w 0 ; ws_kickname
dc.l 0 ; ws_kicksize
dc.w 0 ; ws_kickcrc
; v17
dc.w .config-HEADER ; ws_config
.config dc.b "BW;"
dc.b "C2:B:Enable Joypad Support;"
dc.b "C3:B:Enable ""No Extra Memory Found"" Part;"
dc.b "C1:X:Unlimited Lives:0;"
dc.b "C1:X:Unlimited Energy:1;"
dc.b "C1:X:Unlimited Ammo:2;"
dc.b "C1:X:Unlimited Keys:3;"
dc.b "C1:X:Unlimited Money:4;"
dc.b "C1:X:Start with max. Money:5;"
dc.b "C1:X:Start with max. Keys:6;"
dc.b "C1:X:Start with all Weapons and Map:7;"
dc.b "C1:X:No collision between human players:8;"
dc.b "C1:X:In-Game Keys:9;"
dc.b "C1:X:Strafe Mode when hold fire:10;"
dc.b 0
.dir IFD DEBUG
dc.b "data",0
ENDC
.name dc.b "Alien Breed",0
.copy dc.b "1991 Team 17",0
.info dc.b "By Mr.Larmer/JOTD (until V2.2), StingRay/[S]carab^Scoopex (V2.3)",-1
dc.b "V2.3c patch by ztronzo for no collision and strafe",-1
IFD DEBUG
dc.b "DEBUG!!! "
ENDC
dc.b "Version 2.3c (23.12.2020)",0
HighName dc.b "AlienBreed.high",0
CNOP 0,2
TAGLIST dc.l WHDLTAG_ATTNFLAGS_GET
CPUFLAGS dc.l 0
dc.l WHDLTAG_CUSTOM1_GET
TRAINEROPTIONS dc.l 0
dc.l WHDLTAG_CUSTOM2_GET
JOYPADSUPPORT dc.l 0
dc.l WHDLTAG_CUSTOM3_GET
NOEXTRAMEMPART dc.l 0
dc.l TAG_END
TR_INGAMEKEYS = 9 ; bit for in-game keys options
resload dc.l 0
IGNORE_JOY_DIRECTIONS
include ReadJoyPad.s
Patch lea resload(pc),a1
move.l a0,(a1)
move.l a0,a2
lea TAGLIST(pc),a0
jsr resload_Control(a2)
; install keyboard irq
bsr SetLev2IRQ
move.l NOEXTRAMEMPART(pc),d0
beq.b .normal
moveq #22,d0
moveq #78,d1
lea $40000,a0
move.l a0,a5
bsr Loader
lea PLNOMEM_PRE(pc),a0
lea $40000,a1
jsr resload_Patch(a2)
jmp $40000
.normal
; load and decrypt title
moveq #100,d0
moveq #80,d1
lea $30000,a0
move.l a0,a5
bsr Loader
move.l #80*512,d0
jsr resload_CRC16(a2)
cmp.w #$f265,d0 ; SPS 998
beq.b .ok
.wrongver
pea (TDREASON_WRONGVER).w
bra.w EXIT
.ok
; patch
lea PLTITLE(pc),a0
move.l a5,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
lea $7fffc,a7
lea $7f800,a0
move.l a0,USP
; store ext. mem ptr
move.l HEADER+ws_ExpMem(pc),d0
; memory is aligned like this in the original but this is
; not necessary
;add.l #$60000,d0
;and.l #$fff80000,d0
move.l d0,$7fffc
; create code at $3f4.w
lea $3f4.w,a0
move.l #$53e2577e,d5
move.l #$4b83c5be,d6
move.l #$000041fa,d7
move.l #$1E1B57A1,d2
move.l #$BB83F582,d3
move.l #$7FFF0F8F,d4
eor.l d2,d5
eor.l d3,d6
eor.l d4,d7
move.l d5,(a0)+
move.l d6,(a0)+
move.l d7,(a0)
move.l d5,$200.w
; set default VBI
pea AckVBI(pc)
move.l (a7)+,$6c.w
; and start game
jmp (a5)
QUIT pea (TDREASON_OK).w
EXIT move.l resload(pc),a2
bsr.b KillSys
jmp resload_Abort(a2)
KillSys move.w #$7fff,$dff09a
bsr WaitRaster
move.w #$7ff,$dff096
move.w #$7fff,$dff09c
rts
AckVBI move.w #1<<4+1<<5+1<<6,$dff09c
move.w #1<<4+1<<5+1<<6,$dff09c
rte
PLNOMEM_PRE
PL_START
PL_P $6f4,.patchNoMem1 ; patch after decrunching
PL_END
.patchNoMem1
lea PLNOMEM1(pc),a0
lea $60000+$20,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
jmp $60020
PLNOMEM1
PL_START
PL_P $ae,.patchNoMem ; now patch the real decrunched part
PL_SA $6c,$70 ; skip pea $40(a4)
PL_W $7a,$4e71 ; disable rts
PL_L $38+2,$60000 ; don't trash decruncher code
PL_END
.patchNoMem
lea PLNOMEM(pc),a0
move.l a4,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
move.w #$7fff,(a5)
move.w #$7fff,4(a5) ; disable DMA, original code
move.w d5,sr ; SR: 0, original code
jmp (a4)
PLNOMEM PL_START
PL_PS $1e,.enableKbd
PL_END
.enableKbd
bsr SetLev2IRQ
move.w #$8380,$96(a6) ; original code, enable DMA
rts
PLTITLE PL_START
PL_P $1606,Loader
PL_P $ab66,AckVBI
PL_ORW $e7c+2,1<<3 ; enable level 2 interrupts
PL_P $2046,.patch_premain ; file 1c_15
PL_END
.patch_premain
lea PLPREMAIN(pc),a0
pea $8000
move.l (a7),a1
move.l resload(pc),a2
jmp resload_Patch(a2)
FlushCache
move.l resload(pc),a0
jsr resload_FlushCache(a0)
movem.l (a7)+,d0-a6 ; original code
rts
PLPREMAIN
PL_START
PL_P $241a,.patchmain
PL_P $253e,FlushCache ; flush cache after relocating
PL_END
; main file has been decrypted and relocated, patch it
.patchmain
movem.l d0-a6,-(a7)
lea PLMAIN(pc),a0
move.l a5,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
; patch copperlists in data section
; data section relocation start is $600
; data section offset in executable is $7ee84
lea PLMAIN_CHIP(pc),a0
lea $600.w,a1
jsr resload_Patch(a2)
; load high scores
lea HighName(pc),a0
move.l a5,a1
add.l #$200bc,a1
jsr resload_GetFileSize(a2)
tst.l d0
beq.b .noHigh
lea HighName(pc),a0
move.l a5,a1
add.l #$200bc,a1
jsr resload_LoadFile(a2)
.noHigh
; install trainers
move.l TRAINEROPTIONS(pc),d0
; unlimited lives
lsr.l #1,d0
bcc.b .noUnlimitedLives
eor.b #$19,$749c(a5) ; subq.w <-> tst.w
.noUnlimitedLives
; unlimited energy
lsr.l #1,d0
bcc.b .noUnlimitedEnergy
move.l #$bcd4,d1 ; player 1
move.w #1,(a5,d1.l)
move.w #1,2(a5,d1.l) ; player 2
.noUnlimitedEnergy
; unlimited ammo
lsr.l #1,d0
bcc.b .noUnlimitedAmmo
move.l #$d950,d1
eor.b #$19,(a5,d1.l) ; subq.w <-> tst.w
.noUnlimitedAmmo
; unlimited keys
lsr.l #1,d0
bcc.b .noUnlimitedKeys
move.w #1,$7b3a(a5)
.noUnlimitedKeys
; unlimited money (done in the PLINTEXCOMPUTER patch list)
lsr.l #1,d0
.noUnlimitedMoney
; start with max. money (done in the PLINTEXCOMPUTER patch list)
lsr.l #1,d0
.noMaxMoney
; start with max. keys
lsr.l #1,d0
bcc.b .noMaxKeys
pea 30000
move.l (a7),$5a5a(a5) ; player 1
move.l (a7)+,$61fa(a5) ; player 2
.noMaxKeys
; start with all weapons and map
lsr.l #1,d0
bcc.b .noAllWeapons
move.w #%11111111,$28a0+2(a5)
;addq.w #1,$794(a5) ; "has map" flag is cleared in init part
move.w #$4e71,$d9c(a5)
.noAllWeapons
; start No collision between human players:8;"
lsr.l #1,d0
bcc.b .skipNoCollision
move.w #$6012,$76C6(a5)
move.w #$6012,$7736(a5)
.skipNoCollision
move.l JOYPADSUPPORT(pc),d0
beq.b .noJoypad
bsr _detect_controller_types
.noJoypad
movem.l (a7)+,d0-a6
.nomain lea $7fc00,a7 ; original code
jmp (a5)
PLMAINMENU
PL_START
PL_PS $2d2,.sethiflag ; set "high score achieved" flag
PL_PS $9e,.savehighscores
PL_PSA $181e,.SaveVBI,$1828 ; don't modify VBI code
PL_P $1834,.RestoreVBI ; restore old VBI
PL_P $18d8,.AckVBI
PL_END
.AckVBI move.l HEADER+ws_ExpMem(pc),-(a7)
add.l #$1644,(a7) ; call main interrupt code
rts
.SaveVBI
move.l a0,-(a7)
lea .oldVBI(pc),a0
move.l $6c.w,(a0)
move.l (a7)+,a0
rts
.RestoreVBI
move.l .oldVBI(pc),$6c.w
rts
.oldVBI dc.l 0
.savehighscores
movem.l d0-a6,-(a7)
lea .hiflag(pc),a0
tst.b (a0)
beq.b .nohigh
sf (a0)
move.l TRAINEROPTIONS(pc),d0 ; no saving if any trainers are used
bne.b .nohigh
lea HighName(pc),a0
move.l HEADER+ws_ExpMem(pc),a1
add.l #$200bc,a1
move.l resload(pc),a2
move.l #$6f4-$654,d0 ; size
jsr resload_SaveFile(a2)
.nohigh
movem.l (a7)+,d0-a6
moveq #8,d0 ; optimised original code
rts
.sethiflag
move.l a0,-(a7)
lea .hiflag(pc),a0
st (a0)
move.l (a7)+,a0
clr.b (a0)+ ; original code
clr.b (a0)+
clr.b (a0)+
rts
.hiflag dc.b 0
dc.b 0
PLINTEXCOMPUTER
PL_START
PL_P $a8a,FlushCache ; there is an exe embedded, flush
; cache after relocating
PL_B $2471+14,"A" ; fix "efford" typo :)
; unlimited money
PL_IFC1X 4
PL_W $be6,$4e71 ; sub.l d1,(a5) -> nop (tools)
PL_W $14d2,$4e71 ; sub.l d0,d1 -> nop (weapons)
PL_ENDIF
PL_END
PLMAIN_CHIP
PL_START
PL_ORW ($83fc2-$7ee84)+2,1<<9 ; set Bplcon0 color bit
PL_ORW ($8457e-$7ee84)+2,1<<9 ; set Bplcon0 color bit
PL_END
PLMAIN PL_START
PL_SA $f4c6,$f4d0 ; skip long write to $dff100
PL_P $239ae,FlushCache ; flush cache after relocating
PL_P $ada6,Loader
PL_PS $f61a,ChangeDisk
;PL_AL $10978+2,4 ; fix access fault
;PL_AL $10982+2,4 ; fix access fault
PL_PS $10904,.fix
PL_PSS $21274,AckLev4,2
PL_PSS $17bc,AckVBI_R,2
PL_PSS $17da,AckCOP_R,2
PL_PS $2004e,.checkkeys
PL_P $be2a,QUIT ; reset ("GURU TIME" cheat) -> quit
PL_PS $e754,.PatchMainMenu
PL_PS $d2a8,.PatchIntexComputer
PL_IFBW
PL_PS $e976,.WaitButtonMissionText
PL_ENDIF
PL_P $cf2,.PatchEnd
; Mr.Larmer patches
PL_PS $a6d6,Protection
; JOTD patches
; ztronzo patches START
PL_IFC1X 10
PL_PS $6BC0,.strafe_start
PL_ENDIF
; ztronzo patches END
PL_END
; added by ztronzo START
.strafe_start
cmp.W #$f00c,$2(A0)
beq.b .strafe_check_player1
cmp.W #$f00a,$2(A0)
beq.b .strafe_check_player2
bt.b .no_strafe
.strafe_check_player1
BTST.B #$07,$00bfe001
beq.b .strafe_player1
.strafe_check_player2
BTST.B #$06,$00bfe001
beq.b .strafe_player2
bt.b .no_strafe
.strafe_player1
cmp.W #$f00c,$2(A0)
beq.b .strafe_done
.strafe_player2
cmp.W #$f00a,$2(A0)
beq.b .strafe_done
.no_strafe ; restoring original instructions without strafe
MOVE.W D0,$0140(A0) ; restoring original instructions without strafe
.strafe_done
MOVE.W D2,D0
rts
; added by ztronzo END
.fix move.l (a0)+,d0
bne.b .dest_ok
addq.l #4,d0
.dest_ok
move.l d0,a1
move.w -4(a1),d0
rts
.PatchMainMenu
movem.l d0-a6,-(a7)
lea PLMAINMENU(pc),a0
lea ($a8edc-$7ee84)+$600,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
movem.l (a7)+,d0-a6
move.w #1<<15+1<<3,$dff09a ; enable level 2 interrupts in main menu
rts
.PatchEnd
move.l HEADER+ws_ExpMem(pc),a0
add.l #$20f20,a0
jsr (a0) ; call original routine
move.l #100000*10,d0 ; more than 27 hours should be enough :)
move.l resload(pc),a0
jsr resload_Delay(a0)
bra.w QUIT
.PatchIntexComputer
movem.l d0-a6,-(a7)
move.l a0,a5
lea PLINTEXCOMPUTER(pc),a0
; $600: start of relocated data section
; $a8edc: offset to intex computer executable in binary
; $7ee84: start offset of data section in binary
lea ($a8edc-$7ee84)+$600,a1
move.l resload(pc),a2
jsr resload_Patch(a2)
lea TRAINEROPTIONS(pc),a0
tst.w .moneyset-TRAINEROPTIONS(a0)
bne.b .noMaxMoney
addq.w #1,.moneyset-TRAINEROPTIONS(a0)
move.l (a0),d0
btst #5,d0
beq.b .noMaxMoney
; set 500000 credits
move.l a5,a0
move.l #500000*2*50,(a0)
.noMaxMoney
movem.l (a7)+,d0-a6
jmp ($a8edc-$7ee84)+$600
.moneyset dc.w 0
.WaitButtonMissionText
move.l a0,-(a7)
moveq #10*10,d0 ; 10 seconds
move.l resload(pc),a0
jsr resload_Delay(a0)
move.l (a7)+,a0
moveq #32,d0 ; optimised original code
rts
.pause_status dc.w 0
.checkkeys
bsr.w .getkey
ror.b #$01,d0
not.b d0
cmp.b HEADER+ws_keyexit(pc),d0
beq.w QUIT
; check joypad buttons
move.l JOYPADSUPPORT(pc),d1
beq.b .nojoypad
; clear raw key to avoid problems (f.e. with map screen)
move.l HEADER+ws_ExpMem(pc),a0
add.l #$200ba,a0
clr.b (a0)
move.w d0,-(a7)
bsr ReadJoypad
move.w (a7)+,d0
tst.b d2 ; was a button pressed?
;beq.b .nojoypad
bmi.w QUIT
lea .pause_status(pc),a0
cmp.w #$19,d2
bne.b .noP
tst.b (a0)
beq.b .first_time
moveq #0,d2 ; clear key code -> wait until
bra.b .ok ; button has pressed again
.first_time
st (a0) ; set pause_status flag
bra.b .ok
.noP clr.b (a0)
.ok move.b d2,d0 ; yes, return mapped key
beq.b .nojoypad
lsl.b #$01,d0
not.b d0
rts
.nojoypad
move.l TRAINEROPTIONS(pc),d1
btst #TR_INGAMEKEYS,d1
beq.b .nokeys
move.l HEADER+ws_ExpMem(pc),a5 ; start of executable
lea .TAB(pc),a0
.search movem.w (a0)+,d1/d2
cmp.b d0,d1
bne.b .next
jsr .TAB(pc,d2.w)
bra.b .nokeys
.next tst.w (a0)
bne.b .search
.nokeys
.getkey move.b $bfec01,d0
rts
.TAB dc.w $36,.SkipLevel-.TAB ; n - skip level
dc.w $12,.RefreshEnergy-.TAB ; e - refresh energy
dc.w $27,.MaxKeys-.TAB ; k - get max. keys
dc.w $20,.RefreshAmmo-.TAB ; a - refresh ammo
dc.w $28,.RefreshLives-.TAB ; l - refresh lives
dc.w $25,.GetMap-.TAB ; h - get hand map
dc.w $11,.GetWeapons-.TAB ; w - get all weapons
dc.w 0 ; end of tab
.SkipLevel
move.w #1,$822(a5)
rts
.RefreshEnergy
move.w #$40,$58fa+$150(a5) ; player 1
move.w #$40,$609a+$150(a5) ; player 2
rts
.MaxKeys
move.w #30000,$58fa+$160(a5) ; player 1
move.w #30000,$609a+$160(a5) ; player 2
rts
.RefreshAmmo
move.w #32,$58fa+$15c(a5) ; player 1
move.w #32,$609a+$15c(a5) ; player 2
rts
.RefreshLives
move.w #4,$58fa+$154(a5) ; player 1
move.w #4,$609a+$154(a5) ; player 2
.GetMap move.w #1,$794(a5)
rts
.GetWeapons
move.w #%11111111,d2
move.w d2,$58fa+$192(a5) ; player 1
move.w d2,$609a+$192(a5) ; player 2
rts
; returns result in d2, either mapped rawkey or 0 if no button was pressed
; -1 if quit
ReadJoypad
lea .joy(pc),a0 ; read joystick in port 2 only
move.b controller_joypad_1(pc),d0
beq.b .joy_only
lea .pad(pc),a0 ; read full CD32 pad
.joy_only
jsr (a0)
moveq #0,d2
lea .TAB(pc),a0
.loop move.l joy0_buttons(pc),d0
move.l (a0)+,d1 ; port
beq.b .port0
move.l joy1_buttons(pc),d0
subq.b #1,d1
beq.b .port1
or.l joy0_buttons(pc),d0 ; both ports
.port1
.port0
move.l (a0)+,d1
move.l (a0)+,d3
and.l d1,d0
eor.l d1,d0
bne.b .no_button
move.w d3,d2
.no_button
tst.l (a0) ; check all entries in table
bpl.b .loop
rts
.pad bra.w _read_joysticks_buttons
.joy moveq #1,d0 ; port 1
bsr _read_joystick
lea joy1_buttons(pc),a0
move.l d0,(a0)
rts
; joypad port (0,1,both), joypad button, mapped rawkey
.TAB dc.l 1,JPF_BTN_GRN,$64 ; left alt, change weapons player 1
dc.l 0,JPF_BTN_GRN,$65 ; right alt, change weapons player 2
dc.l 2,JPF_BTN_YEL,$37 ; M, open map
dc.l 2,JPF_BTN_BLU,$40 ; Space, enter intex computer
dc.l 2,JPF_BTN_PLAY,$19 ; P, pause
dc.l 2,JPF_BTN_FORWARD+JPF_BTN_REVERSE,$45 ; ESC
dc.l 2,JPF_BTN_FORWARD+JPF_BTN_REVERSE+JPF_BTN_PLAY,-1 ; quit
dc.l -1 ; end of tab
CNOP 0,2
AckVBI_R
move.w #1<<5,$dff09c
move.w #1<<5,$dff09c
rts
AckCOP_R
move.w #1<<4,$dff09c
move.w #1<<4,$dff09c
rts
AckLev4 move.w #$400,$dff09c
move.w #$400,$dff09c
rts
ChangeDisk
move.l a0,-(a7)
lea DiskNum(pc),a0
move.b #2,(a0)
move.l (a7)+,a0
rts
Protection eor.b #$4E,$458.w ; this code is forgot in cracked version :)
lea Track(pc),a0
moveq #8-1,d0
.copy move.l (a0)+,(a2)+
dbf d0,.copy
; move.l #$77000000,d0
moveq #$77,d0
ror.l #8,d0
move.l #$4449534B,d1
; move.l #$32000000,d2
moveq #$32,d2
ror.l #8,d2
; move.l #$10000000,d3
moveq #$10,d3
ror.l #8,d3
moveq #2,d4
moveq #-1,d6
; move.l #$FFFF,d5
moveq #0,d5
move.w d6,d5
move.l #$55555555,d7
; read track 0_0 from disk 2 with SYNC $8924 to $200 ptr
; and calculated values are left in d0-d7 !
rts
Track
dc.l $8924912A,$AAAA552A,$AAAAAAA4,$A9254449
dc.l $5149112A,$AAAA92AA,$AAAAAAAA,$AAAAAAAA
Loader bsr.b .load
movem.l d0-a6,-(a7)
bsr Decrypt_AB ; decrypt file if necessary
movem.l (a7)+,d0-a6
moveq #0,d0 ; no errors
rts
.load movem.l d0-a6,-(a7)
mulu.w #512,d0
mulu.w #512,d1
move.b DiskNum(pc),d2
move.l resload(pc),a1
jsr resload_DiskLoad(a1)
movem.l (a7)+,d0-a6
rts
DiskNum dc.b 1
dc.b 0
WaitRaster
.wait btst #0,$dff005
beq.b .wait
.wait2 btst #0,$dff005
bne.b .wait2
rts
***********************************
*** Level 2 IRQ ***
***********************************
SetLev2IRQ
pea .int(pc)
move.l (a7)+,$68.w
move.b #1<<7|1<<3,$bfed01 ; enable keyboard interrupts
tst.b $bfed01 ; clear all CIA A interrupts
and.b #~(1<<6),$bfee01 ; set input mode
move.w #1<<3,$dff09c ; clear ports interrupt
move.w #1<<15|1<<14|1<<3,$dff09a ; and enable it
rts
.int movem.l d0-d1/a0-a2,-(a7)
lea $dff000,a0
lea $bfe001,a1
btst #3,$1e+1(a0) ; PORTS irq?
beq.b .end
btst #3,$d00(a1) ; KBD irq?
beq.b .end
moveq #0,d0
move.b $c00(a1),d0
not.b d0
ror.b #$01,d0
or.b #1<<6,$e00(a1) ; set output mode
cmp.b HEADER+ws_keyexit(pc),d0
beq.w QUIT
.nokeys moveq #3-1,d1
.loop move.b $6(a0),d0
.wait cmp.b $6(a0),d0
beq.b .wait
dbf d1,.loop
and.b #~(1<<6),$e00(a1) ; set input mode
.end move.w #1<<3,$9c(a0)
move.w #1<<3,$9c(a0) ; twice to avoid a4k hw bug
movem.l (a7)+,d0-d1/a0-a2
rte
; generic decrypter for all encrypted Alien Breed files
; stingray, 12.07.2018 (13.07.: CLEANCODE added, file 2 decryption fixed)
; code works with full caches
; done for my version of the Alien Breed WHDLoad patch
; if CLEANCODE is set to 1, all encrypted code will be
; cleared with NOP, this way only the real code is left for easy
; disassembling
CLEANCODE = 1 ; 1: clear encryption code with NOPs
; d0.w: start (sector)
; d1.w: length (sectors)
; a0.l: start of encrypted data
Decrypt_AB
move.l a0,a5
mulu.w #512,d1
lea (a0,d1.l),a6 ; a6: end of encrypted file
lea .FTAB(pc),a0
.search movem.w (a0)+,d2/d3 ; start sector, offset to routine
cmp.w d0,d2
beq.b .found
tst.w (a0)
bne.b .search
rts
.found jmp .FTAB(pc,d3.w) ; decrypt file
.FTAB dc.w 2,.file1-.FTAB
dc.w $64,.file2-.FTAB
dc.w $1da,.file3-.FTAB
dc.w $1c5,.file4-.FTAB
dc.w $16,.file5-.FTAB ; no extra memory detected
dc.w 0 ; end of tab
.file1 move.l a6,a0
move.w #$2800/2-1,d0
moveq #-2,d1
.loop0 eor.w d1,-(a0)
rol.w #1,d1
dbf d0,.loop0
lea $826(a5),a4
lea $f9c(a5),a6
bsr.b .decrypt
lea $13e0(a5),a4
lea $2800(a5),a6
bra.b .decrypt
; at offset $6a98 is unused/forgotten code to encrypt the important
; routines
.file2 lea $14(a5),a4
lea $197a(a5),a6
bsr.b .decrypt
lea $19c6(a5),a4
lea $2bd6(a5),a6
bra.b .decrypt
.file3 move.l a5,a4
lea $17f8(a5),a6
bsr.b .decrypt
lea $5d7c(a5),a4
lea $30*512(a5),a6
bra.b .decrypt
.file4 lea $788(a5),a4
bra.b .decrypt
.file5 move.l a5,a4
; a4.l: start of decryption
; a5.l: start of file
; a6.l: end of decryption
.decrypt
.find cmp.w #$41fa,(a4) ; lea xxx(pc),a0
beq.b .start_found
addq.w #2,a4
cmp.l a6,a4
bcs.b .find
rts
.start_found
move.w 4+2(a4),d0 ; loop counter
lea .TAB(pc),a3
.find_opcode
move.w (a3)+,d3 ; offset to check
movem.w (a3)+,d1/d2 ; opcode/routine offset
cmp.w (a4,d3.w),d1
beq.b .instruction_found
tst.w (a3)
bne.b .find_opcode
rts
.instruction_found
move.w 2(a4),a0 ; offset to destination
lea 2(a4,a0.w),a0
lea .TAB(pc,d2.w),a1
jsr (a1) ; call init code
addq.w #2,a1
.decrypt_loop
jsr (a1) ; call decryption code
dbf d0,.decrypt_loop
; search for dbf opcode to find end of decryption loop
.find_end
cmp.w #$51c8,(a4)
beq.b .end_found
IFNE CLEANCODE
move.w #$4e71,(a4)+ ; encryption code -> nop
ELSE ; so real code is left only
addq.w #2,a4
ENDC
cmp.l a6,a4
bcs.b .find_end
rts
.end_found
IFNE CLEANCODE
move.l #$4e714e71,(a4)+ ; disable dbf d0,xxx
ELSE
addq.w #4,a4 ; skip dbf d0,xxx
ENDC
;move.l a4,a2 ; a2: current decryption loop (debug)
bra.b .decrypt
; offset to check, opcode, routine offset
.TAB dc.w 8,$4460,.NegAx-.TAB ; neg.w -(ax)
dc.w 8,$0a60,.EorI-.TAB ; eor.w #xxx,-(ax)
dc.w 8,$0460,.SubI-.TAB ; sub.w #xxx,-(ax)
dc.w 12,$d360,.AddDx-.TAB ; add.w d1,-(ax)
dc.w 8,$4660,.NotAx-.TAB ; not.w -(ax)
dc.w 12,$b360,.EorDx-.TAB ; eor.w d1,-(ax)
dc.w 12,$9360,.SubDx-.TAB ; sub.w d1,-(ax)
dc.w 8,$e6e0,.RorAx-.TAB ; ror.w -(ax)
dc.w 8,$e7e0,.RolAx-.TAB ; rol.w -(ax)
dc.w 8,$0660,.AddI-.TAB ; add.w #xxx,-(ax)
dc.w 8,$4258,.Clr-.TAB ; clr.w (ax)+
dc.w 4,$4298,.Clr-.TAB ; clr.l (ax)+
dc.w 34,$3e20,.Large-.TAB ; move.w -(a0),d7 -> large decryption loop
dc.w 0 ; end of tab
.NegAx bra.b .NegAx_Init
neg.w -(a0)
rts
.NegAx_Init
rts
.NotAx bra.b .NotAx_Init
not.w -(a0)
rts
.NotAx_Init
rts
.RorAx bra.b .RorAx_Init
ror.w -(a0)
rts
.RorAx_Init
rts
.RolAx bra.b .RolAx_Init
rol.w -(a0)
rts
.RolAx_Init
rts
.EorI bra.b .EorI_Init
move.w 8+2(a4),d1
eor.w d1,-(a0)
rts
.EorI_Init
rts
.SubI bra.b .SubI_Init
move.w 8+2(a4),d1
sub.w d1,-(a0)
rts
.SubI_Init
rts
.AddI bra.b .AddI_Init
add.w d1,-(a0)
rts
.AddI_Init
move.w 8+2(a4),d1
rts
.AddDx bra.b .AddDx_Init
add.w d1,-(a0)
rol.w d2,d1
rts
.AddDx_Init
move.w 8+2(a4),d1
moveq #1,d2
cmp.w #$e359,14(a4) ; rol.w #1,d1
beq.b .rol
neg.w d2 ; -> ror.w #1,d1
.rol rts
.EorDx bra.b .EorDx_Init
eor.w d1,-(a0)
rol.w d2,d1
rts
.EorDx_Init
bra.b .AddDx_Init
.SubDx bra.b .SubDx_Init
sub.w d1,-(a0)
rol.w d2,d1
rts
.SubDx_Init
bra.b .AddDx_Init
.Clr bra.b .ClrInit
rts
.ClrInit
moveq #0,d0 ; clear loop counter -> do nothing
; special case: two clr.l (a0)+ instructions without loop
; clr.l (a0)+
; clr.l (a0)+
cmp.w #$4298,6(a4) ; clr.l (a0)+
bne.b .nospecial
move.w #$51c8,4(a4) ; add fake dbf so our "search for end"
; routine will work
.nospecial
rts
.Large bra.b .LargeInit
move.w -(a0),d7
eor.w d1,d7
ror.w d2,d7
rol.w d6,d7
sub.w d5,d7
add.w d6,d7
swap d1
ror.w #4,d7
swap d2
sub.w d2,d7
rol.w #8,d7
eor.w #$C0DE,d7
add.w d2,d7
eor.l d1,d2
sub.w d2,d7
move.w d7,(a0)
sub.l d7,d6
eor.l d7,d5
add.l d7,d5
rts
.LargeInit
move.l 8+2(a4),d1 ; key 1
move.l 14+2(a4),d2 ; key 2
moveq #0,d7
move.l #'L.K.',d6
move.l #'S.B.',d5
rts
|
---|