2024-03-29 11:21 CET

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0005943AlienBreed[WHDLoad Installs Games] slavepublic2022-12-27 10:10
Reporterztronzo 
Assigned ToStingRayProject InfoAlien Breed (Team 17)
http://www.whdload.de/games/AlienBreed.html
 
PrioritynormalSeverityminorReproducibilityalways
StatusassignedResolutionopen 
Summary0005943: Added extra WHDload options by modifying the original slave
DescriptionSrafe/Side-step mode while holding fire/shooting
Allow human players to pass through each other in 2-player mode
TagsNo tags attached.
MachineA1200
CPU68020
CPUSpeed50
ChipSetAGA
GFXCardNone
ChipMem2 MB
FastMem0 MB
WorkbenchOS 3.0
KickROM40 - Kick 3.1
KickSoftNone
WHDLoad18.7
imported
Attached Files
  • ? file icon 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
    
    
    ? file icon AlienBreed.asm (25,129 bytes) 2022-12-25 11:50 +
  • ? file icon 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
    
    
    ? file icon AlienBreed-2.asm (25,432 bytes) 2022-12-27 10:10 +

-Relationships
+Relationships

-Notes

note ~0012168

StingRay (developer)

Thanks, I'll add your additions to the slave code. Is there anything that needs to be added to the ReadMe file (except your credits of course)?

note ~0012173

ztronzo (reporter)

Hello, dont add yet... discovered a problem.. will update you with details.

note ~0012175

StingRay (developer)

Last edited: 2022-12-26 13:17

View 2 revisions

I will not do anything until you give your OK. When you are done, please supply short intructions how the additions can/should be used so that info can be added to the ReadMe.

note ~0012176

retrogamer (reporter)

@StingRay

Please if you are going to update the Alien Breed slave can you merge it with Alien Breed Intro slave?

It makes no sense to have a seperate slave for the intro disk.
+Notes

-Issue History
Date Modified Username Field Change
2022-12-25 11:50 ztronzo New Issue
2022-12-25 11:50 ztronzo File Added: AlienBreed.asm
2022-12-25 11:57 StingRay Assigned To => StingRay
2022-12-25 11:57 StingRay Status new => assigned
2022-12-25 12:00 StingRay Note Added: 0012168
2022-12-25 12:07 StingRay View Status private => public
2022-12-26 12:30 ztronzo Note Added: 0012173
2022-12-26 13:16 StingRay Note Added: 0012175
2022-12-26 13:17 StingRay Note Edited: 0012175 View Revisions
2022-12-26 13:23 retrogamer Note Added: 0012176
2022-12-27 10:10 ztronzo File Added: AlienBreed-2.asm
+Issue History