*******************************************************************************
* Test Trainer (in OS Framework)              Copyright İ 1993-1994 Beldin/ATX
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* $Release	: 1.0 $
* $Revision	: 1.0 $
* $Date		: 26-08-95 $
*
* $Author(s)	: Written by Beldin (In MC680x0 Assembly under Asm-One)
* $Note(s)	: Position Independacy off a4 - (WARNING: DON`T TRASH A4!)
*		: SysBase Ptr is cached so that if running in fastmem access
*		: to SysBase ptr is faster.
*
* $Purpose	: Test trainer frame for DOS games!
*******************************************************************************
*-------------- Definition Includes...

		incdir	include:
		include	os3_gst.i

On	=	1		
Off	=	0
Yes	=	On
No	=	Off

TrainIt	=	Yes			; Patch and execute

*-------------- Definition of Main Variables (Public) Block...

		STRUCTURE VarsBlock,0

		APTR	_SysBase	/* SysBase base */
		APTR	_DosBase	/* DOS lib base */
		APTR	_DosOutput	/* DOS output base */

		APTR	_ReqToolsBase	/* reqtools base */

		APTR	_FileReq	/* ptr to file requester struct */

		APTR	_NumOfHunks	/* num of hunks in struct */

		STRUCT	_FileName,34	/* space to keep filename */
		STRUCT	_DosPath,68	/* full dos path */
		STRUCT	_DosDir,68	/* full dir,0 */

		LABEL	vars_SIZEOF

*******************************************************************************
*-------------- Determine WB/CLI Enviroment (doesn`t corrupt CLI params)

StartUp:	move.l	d0,d7			;save CLI params len
		move.l	a0,a5			;save CLI params ptr
		suba.l	a1,a1			;clear a1
		move.l	4.w,a6			;get execbase
		CALL	FindTask		;find *THIS* task
		move.l	d0,a4			;get task ptr
		move.l	d7,d0			;restore CLI params len
		move.l	a5,a0			;restore CLI params ptr
		tst.l	pr_CLI(a4)		;did we originate from CLI?
		bne.s	ProgStart		;yes... call our program
		lea	pr_MsgPort(a4),a0	;from wb.. handle wb_startup
		move.l	a0,a4
		CALL	WaitPort		;wait for a message
		move.l	a4,a0
		CALL	GetMsg			;then get it
		move.l	d0,-(sp)
		bsr.s	ProgStart
		move.l	d0,d7			;save CLI Return code
		move.l	4.w,a6
		CALL	Forbid
		move.l	(sp)+,a1
		CALL	ReplyMsg
		move.l	d7,d0			;exit code
		rts
*******************************************************************************

VersionStr:	dc.b	'$VER: ATX Dos Game Trainer Beldin/ATX',0 ;for 'version' command
		cnop	0,4			;longword align code..

*-------------- Allocate our Variables (RS.) Area

ProgStart:	move.l	#vars_SIZEOF,d0		;length for our variables
		move.l	#MEMF_PUBLIC+MEMF_CLEAR,d1 ;we want public mem, cleared
		move.l	(AbsExecBase).w,a6	;get SysBase
		CALL	AllocMem		;allocate it...
		move.l	d0,a4			;ptr to our RS.Variables base
		bne.s	RSValid			;did the alloc fail, if so exit
		moveq	#VAR_ERROR,d0		;Memory allocation fail code
		rts				;exit to dos...

*-------------- From here a4 points to our variables area (DON`T DESTROY A4!)

RSValid:	move.l	a6,(a4)			;cache execptr in Public so if

*-------------- Open all libs we want to use

		lea	LibTags(pc),a0		;pt to library script
		bsr.w	OpenTagLibs		;open libraries
		beq.w	_ShutDown		;if failed to open.. exit

*******************************************************************************
*-------------- Program starts here
*******************************************************************************

*-------------- Load file requester.

StartCode:	lea	_LoadTitle(pc),a3
		bsr.w	_FileRequester
		tst.l	d0
		beq.s	_ShutDown

*-------------- Change Dir.
*-------------- Lock on to new dir name, use this lock to change
*-------------- the current dir.

_ChangeDir:	lea	_DosDir(a4),a0
		move.l	a0,d1
		move.l	#ACCESS_READ,d2
		CALLREL	Lock,_DosBase
		move.l	d0,d1			; lock to d1
		CALLREL	CurrentDir,_DosBase

*-------------- Change the cli pointer to current dir.

		lea	_DosDir(a4),a0
		move.l	a0,d1
		CALLREL	SetCurrentDirName,_DosBase

*-------------- Use dos to find the size and load.

		bsr.w	_DosLoadSeg

*-------------- Find the hunk and store hunk address in the _HunkTable.

		bsr.w	_FindHunks

*******************************************************************************
*-------------- Program ends here
*******************************************************************************

*******************************************************************************
* Shutdown() - Free all allocated resources & exit program
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* Frees all previously allocated resources, sanity checks are made so only
* allocated memory/open libraries will be removed.
*******************************************************************************

*-------------- Close Open Libraries

_ShutDown:	lea	LibTags(pc),a0		;ptr to taglist of libs to close
		bsr.w	CloseTagLibs		;close all open libs..
		
*-------------- Free RS Variables Area

		move.l	a4,a1			;ptr to our RS.Variables base
		move.l	#vars_SIZEOF,d0		;no. of bytes to free
		move.l	(a4),a6			;get SysBase
		CALL	FreeMem			;free the memory

		moveq	#SUCCESS,d0		;no return code

*******************************************************************************
*-------------- Patch the bombs in the first hunk.

_TrainerCode:	move.w	#0,d0			; hunk number (0-9)
		bsr	_GetHunkPtr

*-------------- a0 points to the hunk begining,
*-------------- and the hunk offset is in in d0.

.Bombs:		move.l	#$2b610,d0		; a0 = hunk ptr, d0 = offset
		move.w	#$4e71,(a0,d0.l)

.Lives:		move.l	#$11094,d0		; a0 = hunk ptr, d0 = offset
		move.w	#$4e71,(a0,d0.l)

.Pens:		move.l	#$3734c,d0		; a0 = hunk ptr, d0 = offset
		move.w	#$4e71,(a0,d0.l)

*-------------- Put jsr in there k/b handler to jmp to $c0.

		move.l	#$51a32,d0		; a0 = hunk ptr, d0 = offset
		move.w	#$4eb9,(a0,d0.l)	; jmp to $c0
		move.l	#$51a32+2,d0		; a0 = hunk ptr, d0 = offset
		move.l	#$c0,(a0,d0.l)

*-------------- Relocate are keyboard routine to $c0.

		lea	_KeyPatch(pc),a0
		lea	$c0.w,a1
		move.w	#KeyPatchSize,d7
.Loop:		move.b	(a0)+,(a1)+
		dbra	d7,.Loop

*-------------- Execute file,by jumping to the address of the first hunk.

_Execute:	move.l	FileStart,a0
		add.l	a0,a0
		add.l	a0,a0
		lea	4(a0),a1
		jmp	(a1)
.Exit		rts				; exit.
*****************************************************************************
Num_1	=	$01
Num_2	=	$02
Num_3	=	$03
Num_4	=	$04

*-------------- This is a basic keyboard reading routine, which will patch
*-------------- the game code depending on what you whant.

_KeyPatch:	PUSHALL
		move.b	$bfec01.l,d0		; read keyboard
		not	d0
		ror.b	#1,d0

.1		cmpi.b	#Num_1,d0
		bne.s	.2

.2		cmpi.b	#Num_2,d0
		bne.s	.3

.3		cmpi.b	#Num_3,d0
		bne.s	.Exit

.Exit		PULLALL

*-------------- Emulate there game code!

		move.w	$dff01c,d4
		rts
_KeyPatchEnd:
KeyPatchSize	equ	(_KeyPatchEnd-_KeyPatch)-1
*****************************************************************************
*-------------- We will use dos LOADSEG since we whant the hunk structure.

_DosLoadSeg:	move.l	$4.w,a6
		lea	.DosName(pc),a1
		moveq	#0,d0
		jsr	-552(a6)		; open library
		move.l	d0,.DosBase
		move.l	d0,a6

		lea	_DosPath(a4),a0
		move.l	a0,d1
		jsr	-150(a6)		; LoadSeg
		move.l	d0,FileStart

		move.l	$4.w,a6
		move.l	.DosBase,a1
		jsr	-414(a6)		; close library
		rts

.DosBase:	dc.l	0
.DosName:	dc.b	"dos.library",0
		even
*****************************************************************************
_FindHunks:	move.l	FileStart,a1
		lea	HunkTable(pc),a5
.DoAgain:	move.l	a1,a0
		add.l	a0,a0
		add.l	a0,a0
		move.l	a0,d0
		tst.l	d0
		beq.s	.HunksDone
		move.l	(a0),a1
		addq.l	#4,d0
		move.l	d0,(a5)+
		bra.s	.DoAgain
.HunksDone:	rts

FileStart:	dc.l	0
HunkTable:	ds.l	10
*****************************************************************************
* GetHunkPtr()
* ----------------------------------------------------------------------------
*
* Get the hunk pointer.
*
* $Inputs:	d0.w:	Hunk number to get. (0-9)
* $Outputs:	a0:	Hunk pointer.
******************************************************************************
_GetHunkPtr:	asl.l	#2,d0			; make LONG
		lea	HunkTable,a1
		move.l	(a1,d0),a0
		rts
*****************************************************************************
*-------------- Allocate reqtools file requester

_LoadTitle:	dc.b	"Select file to load.....",0
_SaveTitle:	dc.b	"Select file to save.....",0
		even
_ReqTags:	dc.l	RT_ReqPos,REQPOS_CENTERSCR
		dc.l	TAG_DONE
_DeFault_Tags:	dc.l	RTFI_Dir,_DeFaultName
		dc.l	TAG_END
_DeFaultName:	dc.b	'ram:',0
		even

_FileRequester:	PUSHR	a3			; save the title
		move.l	#RT_FILEREQ,d0
		lea	_ReqTags(pc),a0
		CALLREL	rtAllocRequestA,_ReqToolsBase
		move.l	d0,_FileReq(a4)
		beq.s	.ReqError

*-------------- Set are default directory

		lea	_DeFault_Tags(pc),a0
		move.l	d0,a1				; a1 -> file req
		CALLREL	rtChangeReqAttrA,_ReqToolsBase

*-------------- Open the requester

		lea	_ReqTags(pc),a0
		move.l	_FileReq(a4),a1
		lea	_FileName(a4),a2
		clr.b	(a2)
		PULLR	a3			; get the title
		CALLREL	rtFileRequestA,_ReqToolsBase
		tst.l	d0
		beq.s	.FileError

*-------------- Make the full dos path

		lea	_DosPath(a4),a2
		lea	_DosDir(a4),a3

.DoDevice:	move.l	_FileReq(a4),a0
		move.l	rtfi_Dir(a0),a1

.DoDir:		move.b	(a1),(a2)+
		move.b	(a1)+,(a3)+
		bne.s	.DoDir
		cmpi.b	#":",-2(a2)
		beq.s	.DoName
.AddSlash:	suba.l	#1,a2
		move.b	#"/",(a2)+
		clr.b	(a3)
.DoName:	lea	_FileName(a4),a0
.Name:		move.b	(a0)+,(a2)+
		bne.s	.Name

*-------------- Close the file requester

.Done:		move.l	_FileReq(a4),a1
		CALLREL	rtFreeRequest,_ReqToolsBase
		move.l	#-1,d0			; all ok so flag it
		rts

*-------------- Selection canceled or failed!

.FileError	move.l	_FileReq(a4),a1
		CALLREL	rtFreeRequest,_ReqToolsBase

*-------------- Error occured allocating the requester!

.ReqError	moveq.l	#0,d0
		rts
*******************************************************************************
* OSPutStr(string) <NON MODIFIABLE> 
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* Sends a ascii text string to current console output
* 
* $Inputs:	: a0.l = String ptr (null terminated)
* $Output	: void
* $SR-Flags	: void
*******************************************************************************

_OSPutStr:	move.l	a0,d2

*-------------- Calculate string length.

		moveq	#-1,d3			;d4=0
.getlen2:	addq.l	#1,d3			;increase string length by 1
		tst.b	(a0)+			;increase position
		bne.s	.getlen2		;nope not found, so keep on

*-------------- Write string to console.

		move.l	_DosOutput(a4),d1	;dos output
		move.l	_DosBase(a4),a6		;dos base
		CALL	Write			;print error msg to cli
		rts
******************************************************************************
* OpenTagLibs(library_taglist) <NON MODIFIABLE> 
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* $Inputs	: a0.l	= Taglist Pt
* $Format eg;	: dc.w	DOSName-*,_DOSBase,36
*		:
* $Output	: d0.b  = $FF.B if FAILED & $00.B if OKAY
* $SR-Flags	: Z-Flag cleared on FAIL
******************************************************************************
		
OpenTagLibs:	PUSH	d1-d7/a1-a3/a5-a6	;save registers
		move.l	_SysBase(a4),a6		;SysBase in a6
		move.l	a0,a5
.find_tag:	tst.w	(a5)			;TAG_DONE?
		beq.s	.tag_done		;end of taglist?
		move.l	a5,a1			;start of script
		add.w	(a5)+,a1		;a1=library name pt
		moveq	#0,d7			;clear d7
		move.l	d7,d0			;clear d0 for version no.
		move.w	(a5)+,d7		;d7=_XXXBase pt
		move.w	(a5)+,d0		;d0=lib version.
		PUSHR	a1			;stack libname pt
		CALL	OpenLibrary		;try to open desired library
		PULLR	a1			;get libname pt
		move.l	d0,(a4,d7.w)		;save lib base (to RS.)
		bne.s	.find_tag		;did it open? if so open next..
		sf.b	d0			;set Z Flag (d0=$00.B) FAILED!
		bra.s	.pullexit		;clean up stack and return
.tag_done:	st.b	d0			;clear Z Flag (d0=$FF.B) OKAY!
.pullexit:	PULL	d1-d7/a1-a3/a5-a6	;restore registers
		tst.b	d0
		rts				;libraries opened succefully!

CloseTagLibs:	PUSH	d0-d7/a0-a3/a5-a6	;save registers
		move.l	a0,a5			;make copy of taglist ptr
		move.l	_SysBase(a4),a6		;SysBase in a6
.find_tag:	tst.w	(a0)+			;TAG_DONE?
		beq.s	.tag_done		;end of taglist?
		move.l	a4,a1			;get RS. base
		add.w	(a0)+,a1		;create LibBase pt
		move.l	(a1),d0			;is this library open?
		beq.s	.find_tag		;no.. so don`t close it..
		move.l	d0,a1			;base of library to close
		tst.w	(a0)+			;skip version
		PUSHR	a0			;stack script pt
		CALL	CloseLibrary		;close this library
		PULLR	a0			;get script pt
		bra.s	.find_tag		;next tagitem please!
.tag_done:	PULL	d0-d7/a0-a3/a5-a6	;restore registers
script_done:	rts				;all open libraries closed..
******************************************************************************
*- String & Data Variable definitions

*-------------- Open Library definition script

LibTags:	dc.w	DosName-*,_DosBase,36
		dc.w	ReqToolsName-*,_ReqToolsBase,36
		dc.w	TAG_DONE

DosName:	dc.b	"dos.library",0
ReqToolsName:	dc.b	"reqtools.library",0

		END
