;--------------------------------------------------------------------
; Atari Infocom Story Extractor
;--------------------------------------------------------------------
; This program is Copyright © 1995 Mike Fenton

; Feel free though to slice and dice the program however you want.
; Just don't charge your buddy anything for it or we'll tell him he
; could've gotten it for free from us!

; There's a couple of cool little examples of programming included.  I
; suppose you'll come up with even cooler ones that I'll be forced to
; try to out-cool... ;-)

; Note that no animals were harmed in the creation of this program, and
; only pure guess-work went into its making (the hallmark of a true 
; programmer, if I may say so myself).  I have absolutely no idea how an
; actual Infocom database is made.

; (So use this at your own risk!)

		include	exec/exec.i

FUNCCNT		SET	LIB_USERDEF

FUNCDEF		MACRO
_LVO\1		EQU	FUNCCNT
FUNCCNT		SET	FUNCCNT-6
		ENDM

		include	exec/exec_lib.i
		include	dos/dos.i
		include	dos/dos_lib.i
		include	dos/dosextens.i
		include	intuition/intuition.i
		include	intuition/intuition_lib.i
		include	libraries/asl.i
		include	libraries/asl_lib.i
		include	workbench/startup.i

CALLEXEC	MACRO
		movea.l	4.w,a6
		jsr	_LVO\1(a6)
		ENDM

CALLSYS 	MACRO			; call function w/a6 already set
		jsr	_LVO\1(a6)
		ENDM

CALLASL		MACRO			; call ASL
		movea.l	_AslBase,a6
		jsr	_LVO\1(a6)
		ENDM

;--------------------------------------------------------------------
; You can probably skip this part, as it just sets stuff up

		move.l	d0,CliLen	; a0 -> CLI_DATA, d0 = CLI_DATA_LEN
		move.l	a0,CliDat
		moveq	#20,d5			; return code = 20

; Starting?  How...

		suba.l	a1,a1
		CALLEXEC FindTask

		movea.l	d0,a4			; task pointer
		clr.l	returnMsg

		tst.l	pr_CLI(a4)		; BPTR (was it called from CLI?)
		bne.s   go_program		; if so, skip this bit...

; ok, Workbench, how did I get here?

		lea	pr_MsgPort(a4),a0
		CALLSYS WaitPort
		lea	pr_MsgPort(a4),a0
		CALLSYS	GetMsg
		move.l	d0,returnMsg

; look at the system, libraries

go_program	lea	IntName(pc),a1		; Intuition
		moveq	#0,d0
		CALLSYS	OpenLibrary
		move.l	d0,_IntuitionBase	; any kind of intuition?
		beq	QuitStart		; nope, I'm gone!
		movea.l	d0,a0
		cmpi.w	#37,LIB_VERSION(a0)	; 2.04+ ?
		bge.s	.1
		move.l	#IntName,ReqStr
		bsr	MyRequest
		bra	CloseInt

.1		lea	DosName(pc),a1		; Dos
		move.l	#37,d0
		CALLSYS OpenLibrary
		move.l	d0,_DOSBase
		bne.s	.3
		move.l	#DosName,ReqStr
		bsr	MyRequest
		bra	CloseInt

.3		moveq.l	#37,d0
		lea	ASLname(pc),a1		; ASL
		CALLSYS OpenLibrary
		move.l	d0,_AslBase
		bne.s	.4
		move.l	#ASLname,ReqStr
		bsr	MyRequest
		bra	CloseDos

; ok, system checks out... prepare for task

.4		tst.l	returnMsg
		beq.s	.7

		movea.l	returnMsg(pc),a2	; get the argument list
		move.l	sm_ArgList(a2),d0
		beq.s	.7			; nothing really

; get directory WB tells me to use, save current directory

		move.l	d0,a3
		move.l	wa_Lock(a3),d1
		CALLDOS	CurrentDir		; CD to same dir as argument
		move.l	d0,prevDir

; a project icon? well, I'll just look at the first one...

		cmpi.l	#2,sm_NumArgs(a2)
		blt.s	.7

		addq.l	#8,a3			; next arg
		move.l	wa_Lock(a3),UserLock	; save argument directory
		move.l	wa_Name(a3),UserName	; save argument filename
 
; restore pointer and length (CLI)

.7		move.l	CliLen(pc),d0
		movea.l	CliDat(pc),a0

		bsr	_main           	; go

; ok, I'm done...

		move.l	d0,d5			; save condition

; close up system stuff...

		movea.l	_AslBase(pc),a1
		CALLEXEC CloseLibrary
CloseDos	tst.l	returnMsg
		beq.s	.1
		move.l	prevDir(pc),d1
		CALLDOS	CurrentDir		; restore current directory
.1		movea.l	_DOSBase(pc),a1
		CALLEXEC CloseLibrary
CloseInt	movea.l	_IntuitionBase(pc),a1
		CALLSYS CloseLibrary

; put everything back...

QuitStart	tst.l	returnMsg		; Is there a message?
		beq.s	exitToDOS		; if not, skip...

		CALLSYS Forbid          

		move.l	returnMsg(pc),a1
		CALLSYS	ReplyMsg

exitToDOS	move.l	d5,d0			; exit code
		rts

;--------------------------------------------------------------------

MyRequest	suba.l	a0,a0			; default screen
		lea	ReqIText1(pc),a1
		suba.l	a2,a2			; no postext
		lea	OkdIText(pc),a3		; negtext
		moveq	#0,d0
		moveq	#0,d1
		move.w	#185,d2			; width
		move.w	#60,d3			; height
		CALLINT	AutoRequest
		movea.l	4.w,a6			; set vector to exec
		rts

ReqIText1	DC.B    2,1			; black on white
		DC.B    1			; jam2
		DC.B    0
		DC.W    10,5
		DC.L    0			; default font
		DC.L	Bad1			; string ptr
		DC.L    ReqIText2

ReqIText2	DC.B    2,1
		DC.B    1			; jam2
		DC.B    0
		DC.W    10,15
		DC.L    0			; default font
ReqStr		DC.L    0			; string ptr
		DC.L    ReqIText3

ReqIText3	DC.B    2,1
		DC.B    1			; jam2
		DC.B    0
		DC.W    10,25
		DC.L    0			; default font
		DC.L    Version			; string ptr
		DC.L    0

OkdIText	DC.B    2,1
		DC.B    1			; jam2
		DC.B    0
		DC.W    5,3
		DC.L    0			; default font
		DC.L    Okd
		DC.L    0

Okd		dc.b	'Ok',0
Bad1		dc.b	'I can''t find',0
Version		dc.b	'version 37',0

;--------------------------------------------------------------------

DosName		dc.b	'dos.library',0
IntName 	dc.b	'intuition.library',0
ASLname		dc.b	'asl.library',0
		cnop	0,2

;--------------------------------------------------------------------

_DOSBase	dc.l	0
_IntuitionBase	dc.l	0
_AslBase	dc.l	0

CliLen		dc.l	0
CliDat		dc.l	0
returnMsg	dc.l	0
UserLock	dc.l	0
UserName	dc.l	0
prevDir		dc.l	0

;--------------------------------------------------------------------
; ok, ready to really run

_main		clr.b	WorkFile		; buffer
		lea	WorkFile(pc),a3
		move.l	#GFTitle,GFTags+4	; setup tags to read
		move.l	#MyLOK,GFTags+12
		move.b	#$10,GFTags+23
		lea	GFTags(pc),a4		; a4 = tags
		bsr	DoMyReq			; get file name
		tst.l	d0
		beq.s	.ok1
		moveq	#10,d0			; oops, no file!
		rts

; try to open file

.ok1		move.l	#WorkFile,d1
		move.l	#MODE_OLDFILE,d2
		CALLDOS	Open			; open read file
		move.l	d0,File1		; File1 = read file
		bne.s	.ok2
		bsr	IoErrReport
		moveq	#20,d0			; yowza!
		rts

; get length of file and verify validity

.ok2		move.l	d0,d1			; d1 = file handle
		bsr	GetFLen			; get file length
		cmpi.l	#-1,d0
		bne.s	.ok3
		bsr	CloseFiles		; this won't actually return

.ok3		clr.b	Flags			; clear flags
		cmpi.l	#92160,d0		; standard?
		beq.s	.ok4
		cmpi.l	#92176,d0		; 16-byte header?
		beq.s	.ok5
		moveq	#1,d0			; bad length
		bsr	Condition		; report warning
		bra.s	.ok4
.ok5		ori.b	#1,Flags		; set header flag
		moveq	#16,d2
		bsr	MySeek

; get configuration ID (part of boot code)

.ok4		bsr	GetBlock
		move.l	6(a0),d0		; get my ID
		cmpi.l	#$20B91EA2,d0		; old type (Zork)
		beq	.cfg1
		cmpi.l	#$A9008DE7,d0		; improved loader (Infidel)
		beq	.cfg2
		cmpi.l	#$A94F850A,d0		; new loader (Wishbringer)
		beq	.cfg3

		moveq	#4,d0			; unknown configuration
.fail		bsr	Condition		; report problem
.fail2		move.l	File1(pc),d1		; close open files
		beq.s	.ok6
		CALLDOS	Close
.ok6		move.l	File2(pc),d1
		beq.s	.ok7
		CALLDOS	Close
.ok7		moveq	#20,d0			; no um ugh
		rts

; find the starting sector and verify value

.cfg1		moveq	#0,d0
		move.b	$25(a0),d0		; get starting sector #
		cmpi.b	#$39,d0			; $825
		bra	.cont

.cfg2		moveq	#0,d2
		btst	#0,Flags
		beq.s	.sc2
		moveq	#16,d2
.sc2		addi.w	#$1400,d2		; get $1B00 ...
		bsr	MySeek
		bsr	GetBlock
		moveq	#0,d0
		move.b	$22(a0),d0		; get starting sector #
		cmpi.b	#$39,d0
		bra.s	.cont

.cfg3		moveq	#0,d2
		btst	#0,Flags
		beq.s	.sc3
		moveq	#16,d2
.sc3		addi.w	#$1900,d2		; get $2500 ...
		bsr	MySeek
		bsr	GetBlock
		moveq	#0,d0
		move.b	$31(a0),d0		; get starting sector #
		cmpi.b	#$49,d0

.cont		beq.s	.ok8
		move.l	d0,-(a7)		; save d0
		moveq	#3,d0			; bad loader?
		bsr	Condition		; report warning
		move.l	(a7)+,d0		; restore d0

; get first block and check type

.ok8		subq.l	#1,d0			; - 1
		lsl.l	#7,d0			; * 128 (bps)
		moveq	#0,d2
		btst	#0,Flags
		beq.s	.sc4
		moveq	#16,d2
.sc4		add.l	d0,d2			; start position
		bsr	MySeek
		bsr	GetBlock		; get 1st block of data

		cmpi.b	#3,(a0)			; type 3?
		beq.s	.ok9
		move.l	a0,-(a7)		; save a0
		moveq	#2,d0			; bad type?
		bsr	Condition		; report warning
		movea.l	(a7)+,a0		; restore a0

; verify S# is actually numbers

.ok9		moveq	#$12,d1			; offset
		moveq	#5,d0			; length
.snloop		cmpi.b	#'0',(a0,d1.w)
		bcs.s	.badsn			; use carry (unsigned cmp)
		cmpi.b	#'9',(a0,d1.w)
		bhi.s	.badsn
		addq.b	#1,d1
		dbra	d0,.snloop
		bra.s	.goodsn

.badsn		moveq	#7,d0			; bad serial number
		bra	.fail

; get save file and prepare for output

.goodsn		lea	DefFName,a0
		lea	WorkFile2,a1
		bsr	MyCopy256		; copy default name
		move.l	#GF3Title,GFTags+4	; setup tags to save
		move.l	#MySOK,GFTags+12
		move.b	#$30,GFTags+23
		lea	WorkFile2(pc),a3
		lea	GFTags(pc),a4		; a4 = tags
		bsr	DoMyReq			; get file name
		tst.l	d0
		bne	.fail2

		move.l	#WorkFile2,d1
		move.l	#MODE_NEWFILE,d2
		CALLDOS	Open
		move.l	d0,File2		; File2 = write file
		bne.s	.ok10
		bsr	CloseFiles		; won't actually return

; get length of initial block, begin output

.ok10		lea	WorkArea(pc),a0
		moveq	#0,d4
		move.b	4(a0),d4		; get # of pages
		addq.w	#1,d4			; + 1
		lsr.w	#1,d4			; div 2 (# of blocks)

.loop		bsr	PutBlock		; write data
		subq.w	#1,d4
		beq.s	.sp1			; done, skip to next part
		bsr	GetBlock		; get next block
		bra.s	.loop

; switch disks, if necessary

.sp1		bsr	GetBlock
		moveq	#127,d0
		moveq	#0,d1
.sp2		or.l	(a0)+,d1		; add bits to d1
		dbra	d0,.sp2
		tst.l	d1
		beq	.next			; block = 0, continue
		cmpi.l	#$1A1A1A1A,d1		; (may not need this)
		beq	.next

; ok, more data here, check what user thinks...

		lea	HelpMe(pc),a1
		bsr	Request1
		cmpi.l	#1,d0
		blt.s	.next			; get next disk
		beq	.fail2			; abort

; ok, extract the data on this disk

.extract	bsr	PutBlock		; put data
		bsr	GetBlock		; get next block
		moveq	#127,d0
		moveq	#0,d1
.sp3		or.l	(a0)+,d1		; add bits to d1
		dbra	d0,.sp3
		tst.l	d1
		beq.s	.ok11			; block = 0, continue
		cmpi.l	#$1A1A1A1A,d1		; (may not need this)
		bne.s	.extract		; ok, continue

.ok11		bra	IMDone

; ask for next disk file

.next		lea	WorkFile(pc),a3
		move.l	#GF2Title,GFTags+4	; setup tags to read next
		move.l	#MyLOK,GFTags+12
		move.b	#$10,GFTags+23
		lea	GFTags(pc),a4		; a4 = tags
		bsr	DoMyReq			; get file name
		tst.l	d0
		bne	.fail2

		move.l	File1(pc),d1		; close old file
		beq.s	.sp5
		CALLDOS	Close

.sp5		move.l	#WorkFile,d1
		move.l	#MODE_OLDFILE,d2
		CALLDOS	Open			; open read file
		move.l	d0,File1		; File1 = read file
		bne.s	.ok12

		bsr	CloseFiles		; won't actually return

; skip header if found

.ok12		move.l	d0,d1			; d1 = file handle
		bsr	GetFLen			; get file length
		cmpi.l	#-1,d0
		bne.s	.ok13
		bsr	CloseFiles		; this won't actually return

.ok13		cmpi.l	#92160,d0		; standard?
		beq	.ok15
		cmpi.l	#92176,d0		; 16-byte header?
		beq.s	.ok14
		moveq	#1,d0			; bad length
		bsr	Condition		; report warning
		bra	.ok15
.ok14		moveq	#16,d2
		bsr	MySeek

.ok15		bsr	GetBlock
		bra	.extract

;--------------------------------------------------------------------
; Modules (these should probably go before _main, oh well)

GetBlock	move.l	File1(pc),d1		; fh
		move.l	#WorkArea,d2		; buffer
		move.l	#512,d3
		CALLDOS	Read
		cmpi.l	#-1,d0			; error?
		beq.s	CloseFiles
		tst.l	d0			; eof?
		bne.s	.1
		addq.l	#4,a7			; don't go to main
		bra	IMDone			; file is done, I'm done

.1		lea	WorkArea(pc),a0
		rts

PutBlock	move.l	File2(pc),d1		; fh
		move.l	#WorkArea,d2		; buffer
		move.l	#512,d3
		CALLDOS	Write
		cmpi.l	#-1,d0			; error?
		beq.s	CloseFiles
		rts

CloseFiles	bsr	IoErrReport		; report problem
		move.l	File1(pc),d1		; close open files
		beq.s	.ok1
		CALLDOS	Close
.ok1		move.l	File2(pc),d1
		beq.s	.ok2
		CALLDOS	Close
.ok2		moveq	#20,d0			; no um ugh
		addq.l	#4,a7			; don't return to main
		rts

MySeek		move.l	File1(pc),d1		; fh of read file

; (slower than offset_current, but I'm only doing a few of these)
		moveq	#OFFSET_BEGINNING,d3
		CALLDOS	Seek
		CALLSYS	IoErr			; (v37 work-around)
		tst.l	d0
		bne.s	CloseFiles		; yowza!
		rts

IMDone		moveq	#8,d0
		bsr	Condition		; report
		move.l	File1(pc),d1		; close open files
		beq.s	.1
		CALLDOS	Close
.1		move.l	File2(pc),d1
		beq.s	.2
		CALLDOS	Close
.2		moveq	#0,d0			; ugh, uh uh arg (technical)
		rts

;------------------------------------------------------------------
; Misc File Stuff
;------------------------------------------------------------------
; Get length of file by seeking
; (this is a natural for files that are already open)
; d1 = file handle : d0 = length or -1 if error

GetFLen		move.l	d1,-(a7)		; save d1
		moveq	#0,d2
		moveq	#OFFSET_END,d3
		CALLDOS	Seek			; move file cursor to end
		CALLSYS	IoErr			; v37 work-around
		tst.l	d0
		bne.s	.error			; not 0 = problem

		move.l	(a7),d1			; restore d1 (no pop)
		moveq	#0,d2
		moveq	#OFFSET_BEGINNING,d3	; move file cursor to start
		CALLSYS	Seek			; d0 = end position (length)
		move.l	d0,d3			; save d0
		CALLSYS	IoErr			; v37 work-around
		tst.l	d0
		beq.s	.done			; 0 = success

.error		moveq	#-1,d3			; return -1

.done		move.l	d3,d0			; restore d0
		addq.l	#4,a7			; pop d1
		rts

;--------------------------------------------------------------------
; a0 = buffer

AttachFNames	lea	MyDir(pc),a1
		lea	MyFile(pc),a2
		moveq	#0,d0
		moveq	#0,d1
.0		move.b	(a1)+,d0
		beq.s	.1
		move.b	d0,(a0)+		; copy normal chars
		move.b	d0,d1
		bne.s	.0
.1		tst.b	d1		
		beq.s	.2			; no dir string
		cmpi.b	#':',d1
		beq.s	.2			; check for : at end
		cmpi.b	#'/',d1
		beq.s	.2			; check for / at end
		move.b	#'/',(a0)+		; nope, then gimme a slash here
.2		move.b	(a2)+,(a0)+		; copy file name directly
		bne.s	.2
		rts

;------------------------------------------------------------------

DetachFNames	lea	MyDir(pc),a1
		lea	MyFile(pc),a2
		moveq	#0,d0
		moveq	#0,d1
		clr.b	(a2)
.1		addq.b	#1,d1			; d1 = length + 1
		move.b	(a0)+,(a1)+		; copystr
		bne.s	.1
.2		move.b	-(a0),d0		; check prev char
		cmpi.b	#'/',d0			; reached end of dir?
		beq.s	.3
		cmpi.b	#':',d0
		beq.s	.3
		clr.b	-(a1)			; clear file name char
		subq.b	#1,d1			; d1 = current length
		bne.s	.2			; continue...
		bra.s	.4			; oops, no dir, just file
.3		tst.b	d1			; no file name?
		beq.s	.5
		addq.l	#1,a0			; ok, adding file name
.4		move.b	(a0)+,(a2)+		; copy file name
		bne.s	.4
.5		rts

;------------------------------------------------------------------
; a0 = source, a1 = destination (copy until null or a max of 256 bytes)

MyCopy256	move.w	#255,d0
.loop		move.b	(a0)+,(a1)+		; copy (max 256 bytes)
		dbeq	d0,.loop		; loop until null or done
		rts

;--------------------------------------------------------------------
; My requester
;--------------------------------------------------------------------
; (a3 = Buffer, a4 = Req Tags):
; d0 = return code (0 = ok), (Buffer) = new file name

DoMyReq		movem.l	d2/a2/a5/a6,-(a7)	; save regs

		movea.l	a3,a0			; file name buffer
		bsr	DetachFNames
		moveq	#-1,d2			; failed alloc code

		moveq	#0,d0			; type (file requester)
		movea.l	a4,a0			; a0 = * Tags
		CALLASL	AllocAslRequest		; allocate request struct
		move.l	d0,MyReq
		beq.s	.quit			; serious problem

		moveq	#-2,d2			; failed request code

		suba.l	a1,a1			; no tags
		movea.l	d0,a0
		CALLSYS	AslRequest		; gimme file!
		tst.l	d0
		beq.s	.cancel			; cancel

		movea.l	MyReq(pc),a0
		movea.l	rf_Dir(a0),a0		; get ptr to directory string
		lea	MyDir(pc),a1
		bsr	MyCopy256		; MyDir=Dir

		movea.l	MyReq(pc),a0
		movea.l	rf_File(a0),a0		; get ptr to filename string
		lea	MyFile(pc),a1
		bsr	MyCopy256		; MyFile=File
		tst.b	MyFile			; name filled?
		beq.s	.cancel

		movea.l	a3,a0			; buffer
		bsr	AttachFNames
		tst.b	(a3)			; anything?
		beq.s	.cancel

		moveq	#0,d2			; success

.cancel		movea.l	MyReq(pc),a0		; free requester
		CALLSYS	FreeAslRequest

.quit		move.l	d2,d0			; d0 = return code
		movem.l	(a7)+,d2/a2/a5/a6	; restore regs
		rts

;------------------------------------------------------------------
; Error Report
;--------------------------------------------------------------------

IoErrReport	CALLDOS	IoErr			; get error num
		move.l	d0,Status		; store it

		moveq	#6,d0			; get condition string
		bsr	FindCond
		lea	Status(pc),a1		; get * error num
		lea	StuffChar(pc),a2
		lea	MyString(pc),a3
		CALLEXEC RawDoFmt		; format number

		lea	MyString+16(pc),a2
		move.l	Status(pc),d1		; status
		moveq	#0,d2			; header
		move.l	a2,d3			; buffer
		moveq	#127,d4			; len = 127

		CALLDOS	Fault			; get error message

		bra.s	ConReport

Condition	bsr	FindCond
		lea	MyString(pc),a1
.3		move.b	(a0)+,(a1)+
		bne.s	.3

ConReport	lea	CondText(pc),a1

Request1	suba.l	a0,a0			; default screen
		suba.l	a2,a2			; no IDCMP stuff
		CALLINT	EasyRequestArgs
		rts

StuffChar	move.b	d0,(a3)+
		rts

; d0 = # : a0 = * result

FindCond	lea	Conditions(pc),a0
		subq.w	#1,d0
		bmi.s	.1
.2		tst.b	(a0)+
		bne.s	.2
		dbra	d0,.2
.1		rts

;------------------------------------------------------------------
; Data
;------------------------------------------------------------------
; long words...

		cnop	0,4			; align.l

CondText	dc.l	HelpMe-CondText,0
		dc.l	ReqTitle
		dc.l	MyString
		dc.l	Conditions

HelpMe		dc.l	GFTags-CondText,0
		dc.l	ReqTitle
		dc.l	HelpMeTxt
		dc.l	HelpMeGads

GFTags		dc.l	ASL_Hail,GFTitle
		dc.l	ASL_OKText,MyLOK
		dc.l	ASL_FuncFlags,$10	; ($10 load/$30 save)
		dc.l	ASL_File,MyFile
		dc.l	ASL_Dir,MyDir
		dc.l	ASL_Pattern,PFPattern
		dc.l	TAG_DONE

MyReq		dc.l	0
Status		dc.l	0
File1		dc.l	0
File2		dc.l	0

; bytes...

ReqTitle	dc.b	'AInfocom Converter',0
GFTitle		dc.b	'Select disk file',0
GF2Title	dc.b	'Select next disk file',0
GF3Title	dc.b	'Select name of story data file',0
DefFName	dc.b	'ram:Story.data',0
PFPattern	dc.b	'~(#?.info)',0
MyLOK		dc.b	'Load',0
MySOK		dc.b	'Save',0
Conditions	dc.b	'OK',0					; 0
		dc.b	'Warning: Bad Disk File Length!',0	; 1
		dc.b	'Warning: Type may not be supported!',0 ; 2
		dc.b	'Warning: Loader may be corrupted!',0	; 3
		dc.b	'Unknown configuration!',0		; 4
		dc.b	'Unexpected data encountered!',0	; 5
		dc.b	'DOS Error %ld - ',0			; 6
		dc.b	'Bad serial number!',0			; 7
		dc.b	'I''m done.',0				; 8
HelpMeTxt	dc.b	'Extra data found...',10
		dc.b	'(A 2-disk game should',10
		dc.b	'not have extra data.)',10
		dc.b	'Should I extract it or',10
		dc.b	'continue with next disk?',0
HelpMeGads	dc.b	'Abort|Extract|Next Disk',0

; bit 0 = 16 byte header (plenty of room for more flags!)
Flags		dc.b	0

; buffers...

		cnop	0,4			; align.l

MyString	ds.b	144
WorkFile	ds.b	256
WorkFile2	ds.b	256
MyFile		ds.b	256
MyDir		ds.b	256
WorkArea	ds.b	512

