*******************************************************************************
* HunkSeg (in OS Framework)				   (c) 1995 Beldin/ATX
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* $Release	: 1.0 $
* $Revision	: 1.2 $
* $Date		: 24-12-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	: Display hunk structure and run if asked.
*******************************************************************************
*-------------- Definition Includes...

		incdir	include:
		include	os3_gst.i

Yes	=	1
No	=	0

*-------------- 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	_FileStart

		UWORD	_HunkNumber	/* current hunk number */
		UWORD	_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 */

		UBYTE	_QuitFlag	/* 1 = yes, 0 = no */

		APTR	_ArgsPtr	/* argument pointer */
		APTR	_ArgsLength	/* argument length */

		LABEL	vars_SIZEOF

		PUSH	a0/d0		; save the arg and length
*******************************************************************************
*-------------- 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: HunkSeg v1.2 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
*******************************************************************************

StartCode:	PULL	a0/d0			; get the args and length

		move.b	#0,-1(a0,d0)
		move.l	a0,_ArgsPtr(a4)

*-------------- Find the output window.

		CALLREL	Output,_DosBase
		move.l	d0,_DosOutput(a4)

*-------------- Write the about message to the shell window!

		lea	_ATX.msg(pc),a0
		bsr	_OSPutStr

*-------------- Do we whant info?

		move.l	_ArgsPtr(a4),a0
		cmp.b	#"?",(a0)
		bne.s	.Load

		lea	_Info.msg(pc),a0
		bsr	_OSPutStr
		bra	_ShutDown

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

.Load:		lea	_LoadTitle(pc),a3
		bsr.w	_FileRequester
		tst.l	d0
		beq.w	_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

*-------------- Write the hunk info to the shell window!

		clr.w	_HunkNumber(a4)

		move.w	_HunkNumber(a4),d6
		move.w	_NumOfHunks(a4),d7

		lea	_HunkTable(pc),a5
_HunkLoop:	cmp.w	d7,d6
		bge.s	_Rat
		move.l	(a5)+,d5
		add.w	#1,d6

		PUSHALL

*-------------- Convert the hunk address into ascii.

		lea	_WordBuffer(pc),a0
		move.l	d5,d1
		bsr	HexLW2Ascii

*-------------- And write this into the screen update.

		lea	_HunkLoc(pc),a1
		move.l	#_WordBuffer,a0
		move.w	(a0)+,(a1)+
		move.w	(a0)+,(a1)+
		move.w	(a0)+,(a1)+
		move.w	(a0)+,(a1)+

*-------------- Convert the hunk number into ascii.

		lea	_WordBuffer(pc),a0
		move.w	d6,d1
		bsr	HexW2Ascii

*-------------- And write this into the screen update.

		lea	_HunkNumPtr(pc),a1
		move.l	#_WordBuffer,a0
		move.w	(a0),(a1)

*-------------- Write segregation line to the screen.

		lea	_Line.msg(pc),a0
		bsr	_OSPutStr

*-------------- Write hunk structure to the screen.

		lea	_HunkNum.msg(pc),a0
		bsr	_OSPutStr

		PULLALL

		bra.s	_HunkLoop


*-------------- Write segregation line to the screen.

_Rat:		lea	_Line.msg(pc),a0
		bsr	_OSPutStr

*-------------- Write LMB/RMB to the screen.

		lea	_Mouse.msg(pc),a0
		bsr	_OSPutStr

*-------------- Point a0-a5 at hunks 0/1/2/3/4/5 for breakpoint purposes.

		movem.l	a0-a6,-(sp)
		lea	_HunkTable(pc),a6
		move.l	(a6)+,a0
		move.l	(a6)+,a1
		move.l	(a6)+,a2
		move.l	(a6)+,a3
		move.l	(a6)+,a4
		move.l	(a6)+,a5

*-------------- Do we want to quit or run program.

_Mouse:		btst	#6,$bfe001
		beq.s	_Execute
		btst	#$0a,$dff016
		beq.w	_DosUnLoadSeg
		bra.s	_Mouse

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

_Execute:	movem.l	(sp)+,a0-a6
		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

*-------------- Restore the o/s.

		bsr	_ShutDown

*-------------- And execute our file.

		move.l	_RunMe,a0
		add.l	a0,a0
		add.l	a0,a0
		lea	4(a0),a1
		jmp	(a1)

*******************************************************************************
*-------------- We must free the hunks b4 exiting.

_DosUnLoadSeg:	movem.l	(sp)+,a0-a6
		lea	_FileStart(a4),a0
		move.l	(a0),d1			; get 1st hunk ptr
		CALLREL	UnLoadSeg,_DosBase

*******************************************************************************
*-------------- 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
		rts				;exit...
*****************************************************************************
_WordBuffer:	ds.b	10
		even
*****************************************************************************
HexW2Ascii:	move.w	d1,d2
		lsr.w	#4,d2
		bsr	.Nibble
		move.b	d2,(a0)+
		move.w	d1,d2
		bsr	.Nibble
		move.b	d2,(a0)+
		move.b	#0,(a0)			; zero terminate
		rts
.Nibble		and.w	#$0f,d2
		add.w	#$30,d2
		cmp.w	#$3a,d2
		bcs.s	.Ok
		add.w	#7,d2
.Ok		rts
*****************************************************************************
HexLW2Ascii:	move.w	#8-1,d7
.Loop		rol.l	#4,d1
		move.w	d1,d2
		bsr	.Nibble
		move.b	d2,(a0)+
		dbra	d7,.Loop
		move.b	#0,(a0)			; zero terminate
		rts
.Nibble		and.w	#$0f,d2
		add.w	#$30,d2
		cmp.w	#$3a,d2
		bcs.s	.Ok
		add.w	#7,d2
.Ok		rts
*****************************************************************************
*-------------- Allocate reqtools file requester

_LoadTitle:	dc.b	"Select a file to load .....",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.w	.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	.NoSlash
.AddSlash:	suba.l	#1,a2
		move.b	#"/",(a2)+
		clr.b	(a3)
		bra.s	.DoName
.NoSlash:	suba.l	#1,a2
.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
*****************************************************************************
*-------------- We will use dos LOADSEG since we want the hunk structure.

_DosLoadSeg:	lea	_DosPath(a4),a1
		move.l	a1,d1
		CALLREL	LoadSeg,_DosBase
		move.l	d0,_FileStart(a4)
		move.l	d0,_RunMe
		rts
_RunMe:		dc.l	0			; hunk to execute.
*****************************************************************************
_FindHunks:	clr.w	_NumOfHunks(a4)

		move.l	_FileStart(a4),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)+
		add.w	#1,_NumOfHunks(a4)
		bra.s	.DoAgain
.HunksDone:	move.l	#0,(a5)		; null terminate
		rts

_HunkTable:	ds.l	30
*******************************************************************************
* 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
		even
_Info.msg:	dc.b	$0a
		dc.b	" Thank you for using the latest version.  A slight improvement over it's",$0a
		dc.b	" little brother!",$0a
		dc.b	$0a
		dc.b	" Now with cd's to the selected directory, & FULL support of ALL assign's.",$0a
		dc.b	$0a
		dc.b	" At the prompt for L/RMB the pointer to the hunk pointers will be in a0,",$0a
		dc.b	" a1,a2,a3,a4, and a5 so you can break in with your monitor at this point",$0a
		dc.b	" and set breakpoint(s).",$0a
		dc.b	$0a
		dc.b	" As yet there is no parameters(apart from this one) but if you needs",$0a
		dc.b	" some toggles or what ever leave mail on `Digital Candy'."
		dc.b	$0a,$0a,$0a
		dc.b	" Greetings to Cyanide/Lsd and LaZZeR/Anthrox"
		dc.b	$0a,$0a,$0a
		dc.b	" See ya's all later's me m8ty's  -  Beldin/ATX",$0a
		dc.b	$0a,$0a,0
	
_ATX.msg:	dc.b	$0a
		dc.b	$9b,"1;31;40m"		; bold on
		dc.b	" HunkSeg v1.2"
		dc.b	$9b,"0;31;40m"		; bold off
		dc.b	"  -  Beldin/Anthrox",$0a
		dc.b	" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
		dc.b	$0a
		dc.b	0

_HunkNum.msg:	dc.b	$9b,"1;31;40m"		; bold on
		dc.b	"       Hunk_"
		dc.b	$9b,"0;31;40m"		; bold off
_HunkNumPtr:	ds.w	1
		dc.b	":"
_HunkLoc.msg:	dc.b	"  $"
_HunkLoc:	ds.b	8
		dc.b	$0a
		dc.b	0
_Line.msg:	dc.b	"       -------------------",$0a,0
		even

_Mouse.msg:	dc.b	$0a
		dc.b	"    LMB to run /\ RMB to exit",$0a,$0a
		dc.b	0
		even

		END
