	TITLE	SDOS SIMULATOR PACKAGE
* THIS IS AN UNPUBLISHED WORK COPYRIGHTED 1981 BY DENNIS PAINTER.
* USE, DISCLOSURE, OR TRANSFER WITHOUT MY EXPRESS WRITTEN PERMISSION
* IS STRICTLY PROHIBITED.  COPYRIGHT 1981 DENNIS PAINTER.

* VERS DATE 11-22-82.  DWP.
* REV EDIT 11-22-82.  DWP.

	TABS 14,22,40,45,50

*********************************************
*				*
*	MTS-6800/SDOS SIMULATOR		*
*	   VERSION 1.1		*
*				*
*				*
*********************************************

* THIS PACKAGE INTERFACES BETWEEN MTS-6800 AND SOFTWARE DYNAMICS BASIC V1.4.

*	EQUATES

FILEXTENT	EQU	64	64 BLOCK FILE EXTENSIONS

* CURSOR POSITIONING EQUATES

CURPREFIX	EQU	$1B*256+'Y	ESC Y

ROWOFF	EQU	31	OFFSET TO ROW NUMBER
COLOFF	EQU	31	OFFSET TO COLUMN NUMBER

* SWI REQUESTS

SWI:TYPE	EQU	$3F01
SWI:OPEN	EQU	$3F07
SWI:CSTAT	EQU	$3F0A
SWI:LOAD	EQU	$3F10
SWI:RENAME	EQU	$3F0D
SWI:DELETE	EQU	$3F0C
SWI:READ	EQU	$3F02
SWI:READC	EQU	$3F03
SWI:WRITE	EQU	$3F04
SWI:WRITEC	EQU	$3F05
SWI:EXTEND	EQU	$3F0B
SWI:EXIT	EQU	$3F11
SWI:CLOSE	EQU	$3F08
SWI:ABORT	EQU	$3F09
SWI:DATE	EQU	$3F0E
SWI:TIME	EQU	$3F0F
SWI:GERR	EQU	$3F14

* SYSTEM PAGE TEMPLATE

SYSVARS	EQU	$D3	POINTER TO MTS VARIABLES

* NOTE:  EOF IS NOT ALWAYS CORRECT DUE TO BYTE ADDRESSABLE POSITION
* VERSUS BLOCK POSITIONS.  NEEDS TO HAVE TRUE BYTE POSITION TO MEET SPEC.

* BUFFERS SIZES AND OTHER VARIABLES

MAXCHAN	EQU	14	MAXIMUM NUMBER OF CHANNELS.
			;NOTE:  MAXCHAN CANNOT BE INCREASED W/O
			;CHANGING BUFFERS FOR NAMINDX.
MAXBUFS	EQU	12	MAXIMUM NUMBER OF BUFFERED CHANNELS.
MAXCMDSIZ	EQU	18+6	MAXIMUM LENGTH OF A 'COMMAND'
CMDBUFSIZ	EQU	MAXCMDSIZ*2+2	ROOM FOR CMD=CMD<CR>0

* BUGBYTE FOR SOFTWARE DYNAMICS BASIC ETC.

* 7 6 5 4 3 2 1 0  BIT POSITION
* | | | | | |-|-|--UNUSED
* | | | | |--------^G KEY PRESSED - CONTINUE EXECUTION OF SD BASIC
* | | | |----------^V KEY PRESSED - SINGLE STEP SD BASIC
* | | |------------^B KEY PRESSED - SET BASIC BREAKPOINT
* | |--------------^T KEY PRESSED - TRACE SD BASIC
* |----------------<ESC> OR BREAK KEY PRESSED


* CHANNEL TABLE ENTRY TEMPLATE (SETTBLINDEX CURRENTLY LIMITS MAX NUMBER
* OF CHANNELS AS IT ASSUMES # CHANNELS * TABLE SIZE FITS IN ACCB.)

	ABS
	ORG	0

BUFADR	RMB	1
BUFPTR	RMB	2
BUFEND	RMB	1
BLOCKNO	RMB	3
MODFLG	RMB	1
MAXPOS	RMB	4
CHANSTAT	RMB	1
OPENFLAG	RMB	1
EOFFLG	RMB	1
COLCNT	RMB	1	MUST BE LAST LABEL IN TEMPLATE.
	EQU	*

* PAGE ZERO VARIABLES

	ORG	0

SD:IOBLK	EQU	*	I/O BLOCK FOR NON-FILE DEVICES
WRITEBUF	EQU	*
READBUF	RMB	2	BUFFER ADDRESS
BYTECOUNT	RMB	2	BYTECOUNT
SC:PTR	RMB	2	POINTER TO SDOS SYSCALL BLOCK
TBLINDEX	RMB	2	POINTER TO I/O PAK TABLE INDEX

* USED ONLY BY DISPLAY ERROR ROUTINE.

	ORG	0

BLOCKS	RMB	2
DECSTR	RMB	2
PWRSTR	RMB	2
COUNT	RMB	1
* JUMP VECTOR TO ENTRY POINT IS CONSTRUCTED BY THE SDBOOT PROGRAM.

* THE ORDER OF THE FOLLOWING ITEMS SHOULD NOT BE CHANGED, SINCE THE I/O PACKAGE
* BOOTSTRAP PROGRAM ASSUMES THEY ARE HERE:

	REL
	ORG	0

SDOSSIM	JMP	SDOSSIM1	OLD SWITCH VECTOR, NOW ENTRY POINT

IOPKGSIZE	FDB	ENDIOPKG-SDOSSIM	SIMULATOR PACKAGE SIZE.
IOPKGBASE	RMB	2	POINTER TO BASE OF I/O PACKAGE

* LOCATION OF FILE EXTENSION SIZE.  CHANGE TO CHANGE EXTENSION

EXBLKS	FCB	0
	FDB	FILEXTENT	DISK FILE EXTENSION SIZE
BUFSIZ	FCB	MAXBUFS	* FOR LATER USE BY IOPKGBOOT
			;ALSO CONTAINS BUFSIZE SET BY BOOT


BUFTBL	RMB	MAXBUFS	BUFFER TABLE SPACE.
CHANTBL	EQU	*	START OF CHANNEL DATA/STATUS TABLES

* MTS CHANNEL NUMBER (MAXCHAN CANNOT BE GREATER THAN THE SIZE OF THIS TABLE)

CNL1		FCB	0	CONSOLE BUFFER, NONE
		FCB	0,0	BUFPTR
		FCB	0	BUFEND
		FCB	0,0,0	BLOCKNO
		FCB	0	MODFLG
		FCB	0,0,0,0	MAXPOS
		FCB	0	CONSOLE CSTAT
		FCB	$FF	OPEN
		FCB	0	EOFFLG
		FCB	0	COLUMN COUNT
CNL2		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL3		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL4		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL5		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	
CNL6		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL7		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL8		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL9		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL10		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL11		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL12		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL13		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CNL14		FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0


SDOSSIM1	STS	FLAMOUT	SAVE STACK FOR ERRORS
	STX	SC:PTR	SAVE SYSCALL POINTER
	LDAB	2,X	GET CHANNEL NUMBER
	INCB		BUMP IT
	STAB	CHANNEL	AND SAVE
	LDAA	0,X	GET SYSCAL OPCODE
	PSHA		SAVE ON STACK
	JSR	SETTBLINDEX	SET TABLE INDEX
	JSR	ATTNCHECK$	TEST LINE FLAGS
	PULA		RESTORE SYSCALL OPCODE
	CMPA	#$1A+1	CK IF VALID SYSCALL
	BCC	SDOSSIM:ER	B/ SYSCALL # TOO HIGH
	TAB		USE ACCB TO GET INDEX
			;ACCA CONTAINS OPCODE
	ASLB		MULTIPLY BY 2 TO INDEX
	LDX	#VECTORTBL	POINT TO HEAD OF VECTOR TABLE
	JSR	ADDBX	COMPUTE INDEX
	LDX	0,X	GET INDEXED VECTOR
	JMP	0,X	GO TO SYSCALL VECTOR

SDOSSIM:ER	LDX	#1033	***ILLEGAL SYSCALL NUMBER
	SEC
	RTS

VECTORTBL	FDB	OPEN$	:00
	FDB	CREATE$	:01
	FDB	CLOSE$	:02
	FDB	RENAME$	:03
	FDB	DELETE$	:04
	FDB	LOAD$	:05
	FDB	CHAIN$	:06
	FDB	SDOSSIM:ER	:07  CREATE LOG SLOT
	FDB	SDOSSIM:ER	:08  CLOSE LOG SLOT
	FDB	SDOSSIM:ER	:09  SELECT DEFAULT DISK
	FDB	RASCII$	:0A
	FDB	RBIN$	:0B
	FDB	WASCII$	:0C
	FDB	WBIN$	:0D
	FDB	CONTROL$	:0E
	FDB	STATUS$	:0F	
	FDB	WAITDONE$	:10	
	FDB	EXIT$	:11
	FDB	ERROREXIT$	:12	
	FDB	SETERROR$	:13	
	FDB	GETERROR$	:14	
	FDB	DISPERROR$	:15	
	FDB	KILLPROOF$	:16	
	FDB	KILLENABL$	:17	
	FDB	DEBUG$	:18
	FDB	ATTNCHECK$	:19	
	FDB	ISCONSOLE$	:1A	

	PAGE
SETERROR$	LDX	SC:PTR	GET POINTER TO SYSCALL
	LDX	2,X	GET SDOS ERROR CODE
	STX	SDOSERROR	SAVE FOR LATER
	CLC
	RTS

GETERROR$	LDX	SC:PTR	GET POINTER TO SYSCALL
	LDAA	#2	SET EXPECTED LENGTH
	STAA	9,X
	CLR	8,X
	LDAA	SDOSERROR	GET LAST ERROR
	LDAB	SDOSERROR+1
	LDX	10,X	GET POINTER TO ERROR CODE BUFFER
	STAA	0,X	STORE CODE THERE
	STAB	1,X
	CLC
	RTS

DISPERROR$	LDX	#ERRTBL	SEE IF SDOS ERROR CODE IS IN TABLE
	LDAA	SDOSERROR	AND GET MTS ERROR CODE
	LDAB	SDOSERROR+1
DISPER.1	TST	0,X	END TABLE?
	BEQ	DISPER.3	B/ YES, DISPLAY SDOS ERROR NUMBER
	CMPB	2,X	CK LS BYTE FIRST
	BNE	DISPER.2	B/ CODE NOT FOUND
	CMPA	1,X	CK MS BYTE
	BNE	DISPER.2	B/ NOT FOUND
	LDAB	0,X	GET MTS ERROR CODE
	SWI:GERR	GET POINTER TO ERROR TEXT
	BRA	DISPER.5	DISPLAY IT
DISPER.2	INX		ADVANCE LOOK UP TABLE POINTER
	INX
	INX
	BRA	DISPER.1

DISPER.3	LDX	SDOSERROR	GET LAST ERROR CODE
	STX	BLOCKS	SET IN CONVERSION BUFFER

*	JSR	CNVDEC	CONVERT TO DECIMAL
* OLD SUBROUTINE, CONVERT TO DECIMAL.
* TO 5-DIGIT DECIMAL VALUE IN "DECMAL":
* CONVERSION IS TO AN ASCII CODED DECIMAL VALUE

;CNVDEC
	LDX	#$2F2F	INIT DECIMAL VALUE TO ASCII 0 MINUS 1.
	STX	DECMAL
	STX	DECMAL+2
	LDAB	#4
	STAB	COUNT
	LDAA	BLOCKS	GET MS BYTE
	LDAB	BLOCKS+1	GET LS BYTE
	LDX	#PWRS10	INITIALIZE PWRS OF 10 POINTER
	STX	PWRSTR
	LDX	#DECMAL	SET POINTER TO DECIMAL STRING
CNVDE1	STX	DECSTR
CNVDE2	LDX	DECSTR
	INC	0,X	BUMP COUNT
	LDX	PWRSTR	POINT TO NEXT PWR OF 10
	SUBB	1,X	SUB PWR FROM HEX NUMBER
	SBCA	X
	BCC	CNVDE2	B/ KEEP SUBTRACTING
	ADDB	1,X	HEX NUMBER IS STILL POSITIVE.
	ADCA	X
	INX		BUMP POINTER TO POWERS-OF-TEN
	INX		TABLE.
	STX	PWRSTR	SET NEW PWR 10 PTR
	LDX	DECSTR	ADVANCE PTR TO DECIMAL RESULT
	INX
	DEC	COUNT	COUNT OUT DIGITS
	BNE	CNVDE1	B/ NOT DONE
	ADDB	#'0	CONVERT LAST DIGIT TO ASCII
	STAB	0,X	SET LAST DIGIT
	LDX	#DECMAL	SUPPRESS LEADING ZEROS
	LDAB	#4	EXCEPT LAST ONE
CNVD4	LDAA	0,X
	CMPA	#'0	ZERO?
	BNE	CNVD5	B/ NO, DONE
	LDAA	#$20	CONVERT TO BLANK
	STAA	0,X
	INX
	DECB
	BNE	CNVD4
CNVD5	EQU	*	RTS
	LDX	#SDERRMSG
DISPER.5	SWI:TYPE
	CLC
	RTS

ERROREXIT$	LDX	SC:PTR	POINT TO SYSCAL BLOCK
	LDX	2,X	GET ERROR NUMBER
	STX	SDOSERROR	SET IN ERROR CODE
	BEQ	ERROREX$1	B/ NORMAL TERMINATION
	JSR	DISPERROR$	DISPLAY IT
ERROREX$1	JMP	EXIT$

SDERRMSG	FCC	/Error/
DECMAL	RMB	5
	FCB	0
SDOSERROR	FDB	0	LAST SDOS ERROR CODE

STATUS$	JSR	TSTOPEN	TEST FOR CHANNEL OPEN
	LDX	SC:PTR	GET SYSCALL PTR
	LDAA	3,X	GET STATUSCODE
	BNE	STAT1	B/ NOT GET POS
	LDAB	#4	SET REPLY LENGTH
	STAB	9,X
	CLR	8,X
	LDX	TBLINDEX	GET CURRENT BYTE POSTION
	LDAA	BUFPTR+1,X	GET LS BYTE
	PSHA		SAVE ON STACK
	LDAB	BUFPTR,X	COMPUTE POSITION INTO BUFFER
	SUBB	BUFADR,X	B = BUFFER PAGE
	ADDB	BLOCKNO+2,X	ADD PAGE TO BLOCK NUMBER
	PSHB
	LDAB	BLOCKNO+1,X
	ADCB	#0	EXTEND CARRY
	LDAA	BLOCKNO,X
	ADCA	#0
	LDX	SC:PTR	PUT COMPUTED POSTION IN REPLY BUFFER
	LDX	10,X
	STAA	0,X
	STAB	1,X
	PULA
	PULB
	STAA	2,X
	STAB	3,X
	BRA	STATEXIT	B/ DONE
STAT1	CMPA	#1	GET COLUMN?
	BNE	STAT2
	LDX	TBLINDEX
	LDAA	COLCNT,X	GET COLUMN COUNT
	LDX	SC:PTR
	LDAB	#1	LENGTH OF REPLY
	STAB	9,X
	CLR	8,X
	LDX	10,X	POINT TO STATUS BUFFER
	STAA	0,X
	BRA	STATEXIT
STAT2	CMPA	#2	GET EOF?
	BNE	STAT3
	LDX	TBLINDEX
	LDAA	EOFFLG,X	GET EOF FLAG
	LDAB	#1
	LDX	SC:PTR
	STAB	9,X	SET REPLY LENGTH
	CLR	8,X
	LDX	10,X
	STAA	0,X
	BRA	STATEXIT
STAT3	CMPA	#3	GET FILE SIZE?
	BNE	STAT4
	LDX	TBLINDEX
	LDAA	CHANSTAT,X
	BITA	#$20	FILE TYPE?
	BEQ	STAT6	B/ NO, ILLEGAL
	LDX	#STATMSG4
	BRA	STATYPE	TYPE & EXIT
STAT4	CMPA	#4	GETTYP?  (CK CSTAT????)
	BNE	STAT5
	LDX	#STATMSG5
	BRA	STATYPE
STAT5	CMPA	#5
	BNE	STAT6
	LDX	#STATMSG6
STATYPE	SWI:TYPE	DISPLAY FOR DEBUG
STAT6	LDX	#1034	'ILLEGAL DEVICE OPERATION'
	SEC
	RTS

STATEXIT	EQU	*
ISCONSOLE$	EQU	*	NO ACTION BY MTS
WAITDONE$	EQU	*
	CLC
	RTS

STATMSG4	FCC	/STATUS CALL #4/
	FCB	$D,0
STATMSG5	FCC	/STATUS CALL #5/
	FCB	$D,0
STATMSG6	FCC	/STATUS CALL #6/
	FCB	$D,0
* CREATE$:  OPEN AN OUTPUT FILE OR DEVICE.
* OPEN$:    OPEN AN INPUT FILE OR DEVICE.

CREATE$	DEC	BINFLG	SET "CREATE" FLAG.
	BNE	OPEN$1	B/ FLAG SET
	BRA	CREATE$	GO BACK AND SET

OPEN$	CLR	CREATEFLG	SET FLAG FOR "OPEN".

OPEN$1	LDAB	CHANNEL
	CMPB	#MAXCHAN	CHANNEL # TOO HIGH?
	BLS	OPEN$2	B/ NO.
	LDX	#1030	*****SDOS CODE
	JMP	IOERRORX

OPEN$2	LDAB	#7	PRESET ERROR CODE
	LDX	TBLINDEX	GET TABLE INDEX FOR THIS CHANNEL
	LDAA	OPENFLAG,X	TEST IF THIS CHANNEL IS OPEN
	BNE	OPEN$ERROR	B/ ERROR EXIT

*  NOW CHECK IF ATTEMPT TO OPEN THE CLOCK.

	LDX	SC:PTR
	LDAA	6,X	CHECK LENGTH
	BNE	OPEN$2A	B/ NOT CLOCK LENGTH
	LDAA	7,X
	CMPA	#6	IF 6 BYTES, COULD BE CLOCK
	BNE	OPEN$2A	B/ NOT CLOCK.
	LDX	4,X	POINT TO FILE SPEC
	STX	TEMP	SAVE FOR LATER
	LDX	0,X	GET 1ST TWO BYTES
	CPX	#'C*256+'L	IS IT 'CL' ?
	BNE	OPEN$2A	B/ NO, NOT CLOCK.
	LDX	TEMP	RESTORE FILE SPEC POINTER
	LDX	2,X	GET NEXT TWO BYTES
	CPX	#'O*256+'C	IS IT 'OC' ?
	BNE 	OPEN$2A	B/ NO, NOT CLOCK.
	LDX	TEMP
	LDX	4,X	LAST CHANCE
	CPX	#'K*256+':
	BNE	OPEN$2A	B/ NOT THE CLOCK.../
	LDAA	CHANNEL	SET CLOCK CHANNEL FLAG
	STAA	CLOCKCHANNEL
	LDAA	#$00	FAKE SERIAL NON FILE CSTAT
	BRA	OPEN$5	AND SPLIT
OPEN$ERROR	JMP	ERRORSCAN	B/ ACCB CONTAINS MTS ERROR CODE.

OPEN$2A	JSR	MOVECMD	MOVE FILESPEC TO COMMAND BUFFER.
	TST	CREATEFLG	CREATE?
	BEQ	OPEN$3	B/ NO.
	JSR	MOVEQUALS	STICK AN "=" AFTER THE FILESPEC.

OPEN$3	LDAA	CHANNEL	OPEN CHANNEL.
	PSHA		SAVE CHANNEL # ON STACK
	LDX	#OPENBLK
	SWI:OPEN
	PULA		RESTORE CHANNEL NUMBER
	BNE	OPEN$ERROR	B/ ERROR ON OPEN
	SWI:CSTAT	GET CHANNEL STATUS
	BNE	OPEN$ERROR	B/ DID NOT OPEN A CHANNEL
	TST	CREATEFLG	OPEN?, OR CREATE?
	BNE	OPEN$4	B/ CREATE
	BITA	#$10	TEMP FILE? (USER PUT AN "=" SIGN IN SPEC)
	BEQ	OPEN$4	B/ NO
	LDAA	CHANNEL	YES, ABORT CHANNEL AND ERROR
	SWI:ABORT
	LDX	#1024	***ILLEGAL FILE SIZE SPEC
	BRA	OPEN$10A

OPEN$4	PSHA		SAVE CHANNEL STATUS
	JSR	NAMINDX	INDEX CHANNEL TO FILE SPEC SAVE BUFFER
	STX	PAR2	SAVE IN MOVE SUBR PARAMETER LIST
	LDX	SC:PTR
	LDAA	7,X	GET LENGTH TO MOVE
	LDX	4,X	GET POINTER TO FILESPEC
	STX	PAR1	AND SAVE IN MOVE BLOCK
	CMPA	#17	IS LENGTH GREATER THAN MTS SPEC?
	BLS	OPEN$4A	B/ NO
	LDAA	#17	YES, MUST HAVE #NNNNN QUALIFIER
			; DON'T MOVE IT TOO.
OPEN$4A	JSR	MOVE1
	CLR	0,X	TERMINATE THE MOVED SPEC
	JSR	NAMINDX	RESTORE SAVE NAME BUFFER POINTER
	LDAB	#18	GET MAX LENGTH OF NAME
OPEN$4B	LDAA	0,X	LOOK FOR A NULL OR #
	BEQ	OPEN$4C	B/ NULL
	CMPA	#'#	CK IF #
	BEQ	OPEN$4C	B/ FOUND IT
	INX		BUMP POINTER
	DECB
	BNE	OPEN$4B
OPEN$4C	CLR	0,X	ZERO REMAINDER OF BUFFER
	INX
	DECB
	BNE	OPEN$4C
	PULA		RESTORE CSTAT

OPEN$5	LDX	TBLINDEX
	STAA	CHANSTAT,X	SAVE CHANNEL STATUS
	LDAB	#-1	SET OPEN FLAG
	STAB	OPENFLAG,X
	ANDA	#$60	IF IT'S SERIAL NON-FILE,
	BEQ	OPEN$12A	B/ SPLIT
	LDX	#BUFTBL	GET AN UNUSED BUFFER FROM THE BUFFER
	LDAB	#MAXBUFS	TABLE.
OPEN$10	LDAA	X
	BNE	OPEN$12	B/ FOUND ONE.
	INX		BUMP TABLE POINTER.
	DECB
	BNE	OPEN$10	B/ TEST NEXT TABLE ENTRY.
	LDX	#1026	NOT ENOUGH DSKBUFFER POOL IN I/O PAK
OPEN$10A	JMP	IOERRORX

OPEN$12	CLR	X	CLEAR THE BUFFER TABLE ENTRY,
	LDX	TBLINDEX	AND SAVE BUFFER ADDRESS IN THE CHANNEL
	STAA	BUFADR,X	TABLE ENTRY.
	JSR	FILLBUF	FILL THE BUFFER.
OPEN$12A	LDX	SC:PTR	UPDATE SYSCALL BALOCK
	CLR	8,X	SET EXPECTED VALUE
	LDAA	#2
	STAA	9,X
	LDAA	6,X	GET FILENAMELENGTH
	LDAB	7,X
	LDX	10,X	GET RDBUF
	STAA	0,X
	STAB	1,X
	CLC
	RTS
* CLOSE$:  CLOSE FILE OR DEVICE.




CLOSE$	JSR	TSTOPEN	MAKE SURE CHANNEL IS OPEN.

CLOSE$1	TST	BUFADR,X	DOES CHANNEL HAVE A BUFFER?
	BEQ	CLOSE$5	B/ NO.
	JSR	WRTBUF	WRITE OUT BUFFER IF MODIFIED

	LDX	TBLINDEX	GET ADDRESS OF BUFFER,
	LDAA	BUFADR,X
	LDX	#BUFTBL-1	FIND AN EMPTY SLOT IN THE BUFFER TABLE,

CLOSE$3	INX		BUMP BUFFER TABLE PTR TO NXT SLOT
	TST	0,X
	BNE	CLOSE$3
	STAA	0,X	AND STORE BUFFER ADDRESS THERE.

CLOSE$5	LDX	TBLINDEX	CLEAR OUT TABLE PARAMETERS FOR
	LDAB	#COLCNT+1	THIS CHANNEL.
	JSR	CLRFIELD
	LDAA	CHANNEL	CLOSE CHANNEL.
	CMPA	CLOCKCHANNEL	IF CLOCK CHANNEL
	BNE	CLOSE$6	B/ NOT
	CLR	CLOCKCHANNEL	DON'T CALL MTS
	BRA	CLOSE$7
CLOSE$6	SWI:CLOSE
	BNE	DELETE$ERR	USE DELETE ERROR JUMP
CLOSE$7	CLC
	RTS
* DELETE$:	DELETE A FILE.

DELETE$	JSR	MOVECMD	MOVE FILENAME TO COMMAND BUFFER.
	LDX	#CMDBUF	DELETE FILESPEC @ XREG.
	SWI:DELETE
*	BNE	DELETE$ERR	B/ ERROR ON DELETE.
	BEQ	OPEN$12A	UPDATE SYSCALL BLOCK.

DELETE$ERR	JMP	ERRORSCAN	ERROR ON DELETE, LOOK UP ERROR CODE.

* CHAIN$:	LOAD AN OBJECT FILE, JUMP TO FIRST LOCATION.

CHAIN$	JSR	RESET$	RESET EVERYTHING.
	BSR	LOADER	LOAD THE FILE
	BNE	DELETE$ERR	B/ ERROR LOADIN CHAIN FILE
	LDS	$FC	SET UP SDOS STACK
	DES
	JMP	0,X	EXECUTE LOADED PROGRAM

* LOAD$:  LOAD A FILE

LOAD$	BSR	LOADER	LOAD THE FILE
	BNE	DELETE$ERR	ERROR EXIT
	CLC
	RTS		GOOD EXIT

LOADER	JSR	MOVECMD	MOVE STRING TO COMMAND BUFFER.
	LDAA	IOPKGBASE	GET THE IOPACKAGE BASE
	DECA		ADJUST FOR LOAD ROUNDING UP
	JSR	CNVASCII	CONVERT TO ASCII
	STX	LOADMAX	SAVE IN LOAD STRING
	LDX	#$3030	ALONG WITH 2 ZEROS
	STX	LOADMAX+2
	LDAA	#',	STICK A COMMA
	STAA	LOADELIM	IN AS DELIMITER
	LDX	#LOADBUF	LOAD OBJECT FILE.
	SWI:LOAD
	RTS

* RENAME$:	RENAME FILE.

RENAME$	JSR	MOVECMD	MOVE NEW FILENAME TO COMMAND BUFFER.
	JSR	MOVEQUALS	AND AN EQUALS
	JSR	NAMINDX	INDEX TO CHANNEL NUMBER NAME
	STX	STRING	SAVE FOR MOVE
	CLRA		COUNT LENGTH OF OLD FILE NAME
LOOP	SET	*
	INX
	INCA
	LDAB	0,X
	BNE	LOOP
	LDX	#STRING
	JSR	MOVE
	LDX	#CMDBUF
	SWI:RENAME
	BNE	DELETE$ERR
	CLC
	RTS
* RBIN$:	READ BINARY CHARACTER.
* RASCII$:	READ ASCII CHARACTERR.

RBIN$	DEC	BINFLG	SET "BINARY" FLAG.
	BNE	RASCII$1A
	BRA	RBIN$	B/ NOT SET YET

RASCII$	CLR	BINFLG	FLAG ASCII MODE.
RASCII$1A	LDX	SC:PTR
	LDAB	3,X	GET MODE FLAG
	STAB	LMFLG
	CLR	8,X	ZERO # BYTES XFERED
	CLR	9,X
	LDX	10,X	GET BUFFER POINTER
	STX	READBUF	SAVE IT
	LDX	SC:PTR
	LDX	12,X	GET BYTE COUNT
	STX	BYTECOUNT
	JSR	TSTOPEN	MAKE SURE CHANNEL IS OPEN.
	LDAB	EOFFLG,X	EOF?
	BNE	RASCII$7W	B/ YES
	ANDA	#$60	SERIAL NON-FILE?
	BNE	RASCII$8	B/ NO.
	LDX	#SD:IOBLK	POINT TO BUFFER & BYTE COUNT
	LDAA	CHANNEL	GET CHANNEL NUMBER
	CMPA	CLOCKCHANNEL	CK IF READ IS FROM CLOCK
	BNE	RASCII$5B	B/ NOT READ CLOCK
	JSR	READ:CLOCK
	LDAB	#17	17 BYTES READ BACK
	BRA	RASCII$5E	EXIT

RASCII$5B	TST	LMFLG	LINE MODE?
	BEQ	RASCII$6	B/ NO, DO SPECIAL
	LDAB	#131	PRESET MAX BYTE COUNT
	TST	2,X	CK MSB BYTE COUNT
	BNE	RASCII$5D	B/ TOO HIGH
	CMPB	3,X	CK LSB BYTE COUNT
	BCC	RASCII$5C	B/ OK
RASCII$5D	CLR	2,X	REDUCE BYTE COUNT TO 131
	STAB	3,X
RASCII$5C	SWI:READ	ASCII MODE: LINE EDITING.
	BNE	RASCII$7X	B/ ERROR.  WONDER WHAT?
	LDAA	#$D	SEARCH FOR A <CR>
	LDX	READBUF	COUNT # CHARACTERS INPUT
	DEX		ADJUST FOR 1ST TIME INTO LOOP
	CLRB		MUST HAVE 1 <CR>
RASCII$5A	INX		BUMP PTR
	INCB		AND CHAR COUNT
	CMPA	0,X	<CR>?
	BNE	RASCII$5A	B/ NO, KEEP LOOKING
	LDX	TBLINDEX	SET COLUMN COUNT
	CLR	COLCNT,X	<CR>, REMEMBER?
	BRA	RASCII$7C	SET COUNT FOR SDOS BLOCK

RASCII$6	SWI:READC	BINARY MODE: NO EDITING.
	BNE	RASCII$7X	B/ ERROR
	LDAB	BYTECOUNT+1	GET BYTE COUNT 255 COUNT MAX
RASCII$5E	TBA		IN  BOTH ACC'S
	LDX	TBLINDEX
	ADDA	COLCNT,X	SET COLUMN COUNT
	STAA	COLCNT,X
RASCII$7C	LDX	SC:PTR
	STAB	9,X	SET BYTE COUNT
	CLC
	RTS		DONE!

RASCII$7W	LDAB	#$C	SET MTS EOF ERROR & GO LOOK UP SD ERROR
RASCII$7X	JMP	ERRORSCAN

RASCII$8	JSR	TESTBUF	IF BUFFER IS FULL, READ IN A NEW ONE.
	BNE	RASCII$7W	B/ EOF HIT
	LDAB	COLCNT,X	GET COLUMN COUNT
	LDX	BUFPTR,X	GET I/O PAK BUFFER PTR
	LDAA	0,X	GET A CHARACTER
	LDX	TBLINDEX	RESTORE INDEX
	INC	BUFPTR+1,X	ADVANCE BUFFER POINTER
	BNE	RASCII$8A
	INC	BUFPTR,X	ON MEMORY PAGE BOUNDARY
RASCII$8A	TST	BINFLG	BINARY MODE?
	BNE	RASCII$10	B/ YES, IGNORE COLUMN COUNT, ETC.
	ANDA	#$7F	STRIP PARITY BIT
	BEQ	RASCII$8	IGNORE NULLS
	CMPA	#$7F	AND RUBOUTS
	BEQ	RASCII$8
	CMPA	#$20
	BCC	RASCII$9C	B/ PRINTING CHAR
	CMPA	#$D	<CR>?
	BNE	RASCII$9B	B/ NO
	CLRB
	CLR	COLCNT,X	ZERO COLCNT
	TST	LMFLG	LINE MODE?
	BEQ	RASCII$11	B/ NO
	LDX	#1	SET BYTE COUNT TO 1 FOR EXIT
	STX	BYTECOUNT
	BRA	RASCII$10	EXIT
RASCII$9B	CMPA	#$8	BACK SPACE?
	BNE	RASCII$9C
	TSTB		ALREADY ON COL ZERO?
	BEQ	RASCII$11	B/ YES
	DECB
	DECB
RASCII$9C	INCB		BUMP COLCNT
RASCII$11	STAB	COLCNT,X
RASCII$10	LDX	READBUF
	STAA	0,X
	INX
	STX	READBUF
	LDX	SC:PTR
	INC	9,X
	BNE	RASCII$12
	INC	8,X
RASCII$12	LDX	BYTECOUNT
	DEX
	STX	BYTECOUNT	TEST FOR DONE
	BNE	RASCII$8
	CLC
	RTS


READ:CLOCK	SWI:TIME	GET MTS TIME
	STX	PAR1	INITIALIZE SOURCE STRING
	LDX	READBUF
	STX	PAR2	INITIALIZE DESTINATION STRING
	LDAA	#8	COPY 8 BYTES
	JSR	MOVE1	MOVE BYTES IN
	LDAA	#' 	PUT IN A BLANK DELIMITER
	STAA	0,X
	LDAA	#'/
	STAA	3,X
	STAA	6,X
	INX
	STX	PAR2
	SWI:DATE
	STX	PAR1
	LDAA	#2
	JSR	MOVE1
	INX
	STX	PAR2
	LDAA	#2
	JSR	MOVE1
	INX
	STX	PAR2
	LDAA	#2
	JSR	MOVE1
	RTS


* IF BUFFER IS FULL, READ IN A NEW ONE:
* ON ENTRY X-REG AT CHANNEL TABLE INDEX.
* ON EXIT X-REG AT CHANNEL TABLE INDEX.
* OTHER REGISTERS DESTROYED

TESTBUF	LDX	TBLINDEX	SET CHANNEL TABLE INDEX
	LDAB	BUFPTR+1,X	DOES BUFPTR = BUFEND?
	BNE	TESTBUF2	B/ NO.
	LDAA	BUFPTR,X	GET REST OF BUFPTR
	CMPA	BUFEND,X
	BNE	TESTBUF2	B/ NO. NOT AT END YET
	JSR	WRTBUF	IF MODIFIED WRITE OUT OLD BUFFER


* ENTRY POINT TO UPDATE BLOCK NUMBER AFTER EXTEND


TESTBUF1	LDX	TBLINDEX	BUMP BLOCKNO IN CHANNEL TABLE, I.E.
	LDAA	BUFEND,X	BLOCKNO = BLOCKNO + (BUFEND - BUFADR).
	SUBA	BUFADR,X
	ADDA	BLOCKNO+2,X
	STAA	BLOCKNO+2,X
	BCC	TESTBUF1A
	INC	BLOCKNO+1,X
	BNE	TESTBUF1A
	INC	BLOCKNO,X

* ENTRY POINT TO FILL BUFFER AFTER POSITION

TESTBUF1A	JSR	FILLBUF	READ IN A NEW BUFFER.
;	LDX	TBLINDEX
	LDAB	EOFFLG,X	EOF HIT?
	RTS

TESTBUF2	CLRA		CLEAR Z-BIT SO WE KNOW EOF WASN'T HIT.
	RTS
* WBIN$:	WRITE BINARY CHARACTER.
* WASCII$:	WRITE ASCII CHARACTER.

WBIN$	DEC	BINFLG	SET BINARY MODE FLAG.
	BNE	WASCII$1
	BRA	WBIN$	B/ FLAG NOT SET YET

WASCII$	CLR	BINFLG	FLAG ASCII MODE.
WASCII$1	JSR	TSTOPEN	MAKE SURE CHANNEL IS OPEN.
	LDX	SC:PTR	GET PARAMS
	LDX	4,X	GET SD BUFFER
	STX	WRITEBUF
	LDX	SC:PTR
	LDX	6,X	SET SD BYTE COUNT
	STX	BYTECOUNT
	BEQ	WASCII$2L	B/ NOTHING TO WRITE
	ANDA	#$60	SERIAL NON-FILE?
	BNE	WASCII$3	B/ NO, PUT DATA IN BUFFER
	LDX	#SD:IOBLK
	LDAA	CHANNEL
	TST	BINFLG	CK MODE
	BNE	WASCII$2
	SWI:WRITE	ASCII MODE: EDITING.
	BRA	WASCII$2A
WASCII$2	SWI:WRITEC	BINARY MODE: NO EDITING.
WASCII$2A	BEQ	WASCII$2B	B/ NO ERRORS.

WASCII$ER	JMP	ERRORSCAN

WASCII$2B	LDAB	BINFLG	BINARY MODE?
	BNE	WASCII$2I	B/ YES, DONE
	LDX	TBLINDEX	COMPUTE PRINT POSITION
	LDAB	COLCNT,X	GET CURRENT COLCNT
WASCII$2D	LDX	WRITEBUF	GET THE POINTER TO DATA
	LDAA	0,X	CK A BYTE
	INX
	STX	WRITEBUF
	ANDA	#$7F	SHOULD BE ASCII, BUT...
	BEQ	WASCII$2H	B/ DON'T COUNT NULLS IN COLCNT
	CMPA	#$7F	RUBOUT?
	BEQ	WASCII$2H	B/ DITTO RUBOUTS
	CMPA	#$20	PRINTING CHAR?
	BCC	WASCII$2J	YES, BUMP COLCNT, ETC.
	CMPA	#$D	<CR>?
	BNE	WASCII$2E	B/ NO
	CLRB		YES, ZERO COLCNT
WASCII$2E	CMPA	#$8	BACKSPACE
	BNE	WASCII$2H
	TSTB		ALREADY ON ZERO?
	BEQ	WASCII$2H	B/ YES, LEAVE IT THERE
	DECB
	DECB
WASCII$2J	INCB
WASCII$2H	LDX	BYTECOUNT
	DEX
	STX	BYTECOUNT
	BNE	WASCII$2D	B/ NOT DONE
WASCII$2I	LDX	TBLINDEX
	STAB	COLCNT,X
WASCII$2L	CLC
	RTS		DONE WITH NON BUFFERED WRITE

WASCII$3	JSR	TESTBUF	IF BUFFER IS FULL, READ IN A NEW ONE.
	BEQ	WASCII$5	B/ EOF NOT HIT.
	JSR	TSTOPEN	GET CHANNEL STATUS.
	BITA	#$10	TENTATIVE FILE?
	BNE	WASCII$4	B/ YES.
	LDX	TBLINDEX	SET EOF HIT FLAG
	LDAB	#$C
	STAB	EOFFLG,X	AND EXTEND PERM FILE
WASCII$4	LDAA	CHANNEL	EXTEND TENTATIVE FILE BY 64 BLOCKS.
	LDX	#EXBLKS
	SWI:EXTEND
	BNE	WASCII$ER	B/ ERROR ON FILE EXTEND
	JSR	TESTBUF1	GO COMPUTE NEW BLOCK NO

WASCII$5	LDAB	COLCNT,X	GET COLCNT IN ACCB
	LDX	WRITEBUF	GET A CHARACTER
	LDAA	0,X
	INX
	STX	WRITEBUF
	LDX	TBLINDEX	RESTOR INDEX
	TST	BINFLG	BINARY MODE?
	BEQ	WASCII$5B	B/ NO
WASCII$5A	CLRB		ZERO COLCNT
	BRA	WASCII$6B	STUFF IT AND CHAR
WASCII$5B	ANDA	#$7F	ASCII MODE, EDIT
	BEQ	WASCII$8	B/ IGNORE NULLS
	CMPA	#$7F
	BEQ	WASCII$8	AND RUBOUTS
	CMPA	#$20	PRINTING CHAR?
	BCC	WASCII$6A	B/ YES
	CMPA	#$D	<CR>?
	BEQ	WASCII$5A	B/ YES
	CMPA	#$8	BACK SPACE?
	BNE	WASCII$6A	NO, COUNT IT ANYWAY
	TSTB		ON COLUMN ZERO?
	BEQ	WASCII$6B	B/ YES, DON'T DECREMENT
	DECB
	DECB		TWICE TO ADJUST
WASCII$6A	INCB		BUMP PRINT HEAD POS
WASCII$6B	STAB	COLCNT,X	SAVE IT
	LDX	BUFPTR,X	STORE CHARACTER IN BUFFER.
	STAA	X
	LDX	TBLINDEX	BUMP BUFFER POINTER.
	INC	BUFPTR+1,X
	BNE	WASCII$6
	INC	BUFPTR,X
WASCII$6	LDAB	#1	SET "BUFFER MODIFIED" FLAG.
	STAB	MODFLG,X
WASCII$8	LDX	BYTECOUNT
	DEX
	STX	BYTECOUNT
	BNE	WASCII$3
	CLC
WASCII$7	RTS
* TEST IF BUFFER HAS BEEN MODIFIED IF SO WRITE OUT BUFFER CONTENTS:
*
* ENTER WITH TABLE INDEX IN X-REG

WRTBUF	TST	MODFLG,X	BUFFER MODIFIED?
	BEQ	WASCII$7	NO, JUST RETURN
			;CALCULATE CURRENT POSITION IN FILE:
	LDAA	BLOCKNO,X	POSITION = (BLOCKNO * $100) +
	LDX	BLOCKNO+1,X	(BUFPTR - BUFADR).
	STAA	POSITION
	STX	POSITION+1
	LDX	TBLINDEX
	LDAA	BUFPTR+1,X
	STAA	POSITION+3
	LDAA	BUFPTR,X
	SUBA	BUFADR,X
	ADDA	POSITION+2
	STAA	POSITION+2
	BCC	WRTBUF1
	INC	POSITION+1
	BNE	WRTBUF1
	INC	POSITION

WRTBUF1	JSR	SETMAXPOS	SET MAXIMUM POSITION IN FILE.
	JSR	SETIOBLOCK	SET I/O BLOCK PARAMETERS.
	LDX	TBLINDEX	BYTE COUNT = BUFEND - BUFADR.
	LDAA	BUFEND,X
	SUBA	BUFADR,X
	STAA	IOBLOCK+2
	LDAA	CHANSTAT,X	TENTATIVE FILE?
	ANDA	#$70
	CMPA	#$70
	BNE	WRTBUF4	B/ NO.
	LDAA	MAXPOS+2,X	YES: IF MAXIMUM POSITION FALLS WITHIN
	SUBA	BLOCKNO+2,X	BUFFER,
	LDAB	MAXPOS+1,X	I.E. (MAXBLOCKNO - BLOCKNO)
	SBCB	BLOCKNO+1,X	< I/O BLOCK BYTE COUNT,
	BNE	WRTBUF4
	LDAB	MAXPOS,X
	SBCB	BLOCKNO,X
	BNE	WRTBUF4
	CMPA	IOBLOCK+2
	BCC	WRTBUF4
	LDAB	MAXPOS+3,X	THEN: NULL FILL FROM MAXIMUM POSITION
	ADDA	BUFADR,X	TO NEXT PAGE BOUNDARY.
	STAA	TEMP
	STAB	TEMP+1
	LDX	TEMP
	TSTB
	BEQ	WRTBUF3A	B/ DONE.
WRTBUF2	CLR	X
	INX
	INCB
	BNE	WRTBUF2
	INCA		SET PARTIAL BYTE COUNT IN I/O BLOCK.
WRTBUF3A	LDX	TBLINDEX
	SUBA	BUFADR,X
	STAA	IOBLOCK+2

WRTBUF4	LDX	#IOBLOCK	WRITE CHANNEL
	LDAA	CHANNEL
	SWI:WRITE
	BEQ	READBUF2	B/ NO ERROR.  EXIT.
WRTBUFERR	JMP	ERRORSCAN	WE ALWAYS READ INTO THE BUFFER BEFORE
			; WRITING IT OUT, SO AN EOF SHOULD NEVER
			; OCCUR.
* READ IN A NEW BUFFER:

FILLBUF	LDX	TBLINDEX	CLEAR "EOF" AND "BUFFER-MODIFIED" FLAGS.
	CLR	EOFFLG,X
	CLR	MODFLG,X
	LDAA	BUFADR,X	RESET BUFFER POINTER.
	STAA	BUFPTR,X
	CLR	BUFPTR+1,X
	JSR	SETIOBLOCK	SET I/O BLOCK PARAMETERS.
	LDX	#IOBLOCK	READ CHANNEL.
	LDAA	CHANNEL
	SWI:READ
	TPA		SAVE CONDITION CODES
	PSHA
	LDAA	IOBLOCK	SET BUFEND = ADDRESS IN I/O BLOCK.
	LDX	TBLINDEX
	STAA	BUFEND,X
	PULA		RESTORE CONDITION CODES.
	TAP
	BEQ	READBUF2	B/ NO ERROR.
	CMPB	#12	EOF?
	BNE	WRTBUFERR	B/ NO, SCAN ERROR LIST
	LDAA	BUFADR,X	IF BUFFER IS EMPTY,
	CMPA	BUFEND,X
	BNE	READBUF2
	STAB	EOFFLG,X	SET EOF FLAG

READBUF2	RTS
* POSITION FILE:
CONTROL$	LDX	SC:PTR	GET SYSCALL POINTER
	LDAA	3,X	GET CONTROL PARAMETER BYTE
	BEQ	POSITION$	POSITION REQUESTED
	LDX	#1034	GIVE ILLEGAL DEVICE OPERATION FOR
	BRA	POSITION$A	DUMP BUFFER CALL.

POSITION$	LDX	4,X	POINT TO POSITION DATA
	STX	STRING	SAVE WHERE REST OF ROUTINE EXPECTS IT
	JSR	TSTOPEN	MAKE SURE CHANNEL IS OPEN.
	ANDA	#$60	SERIAL NON-FILE?
	BNE	POSITION$1	B/ NO.
	LDX	STRING	POINT TO POSITION DATA
	LDAA	2,X	GET ROW ADDRESS
	ADDA	#ROWOFF+1	SET TO SCREEN CONTROL CODE
	STAA	ROWBYTE
	LDAA	3,X	GET COLUMN ADDRESS
	ADDA	#COLOFF+1
	STAA	COLBYTE
	LDAA	CHANNEL
	CMPA	#1	CONSOLE?
	BEQ	POS$CRT	B/ YES
	JSR	NAMINDX	LOOK UP FILE SPEC
	LDAA	0,X
	JSR	FOLD	MAKE SAME CASE
	CMPA	#'T
	BNE	POSITION$B	B/ NOT TT: OR TT0:
	TAB		SAVE IN B
	LDAA	1,X	CK NEXT CHAR
	JSR	FOLD
	CBA		CK IF TT
	BNE	POSITION$B	B/ NOT TT
	LDX	2,X	REMAINDER MAY BE :NULL OR 0:
	CPX	#':*256	CK IF COLON NULL
	BEQ	POS$CRT	B/ OK ITS A TT:
	CPX	#'0*256+':	CK IF TT0: WAS SPEC
	BNE	POSITION$B	B/ NO, ERROR
POS$CRT	LDX	#GOXYSTR	POINT TO STRING
	SWI:TYPE	POSITION CRT CURSOR
	CLC
	RTS
POSITION$B	LDX	#1004	*****BAD FILE POSITION REQUESTED
POSITION$A	JMP	IOERRORX

POSITION$1	JSR	POSBUFPTR1	IS NEW POSITION WITHIN CURRENT BUFFER?
	LDX	X	(I.E. NEWPOSITIONBLOCKNO - BLOCKNO <
			; BUFEND - BUFADR)
	BNE	POSITION$2	B/ NO.
	LDX	TBLINDEX
	LDAA	BUFEND,X
	SUBA	BUFADR,X
	CMPA	DIFFERENCE+2
	BHI	POSBUFPTR	YES: POSITION BUFFER POINTER,
			;NO SET POSITION & FILL BUFFER
POSITION$2	LDX	TBLINDEX
	JSR	WRTBUF	WRITE OLD BUFFER OUT IF MODIFIED

	JSR	SETMAXPOS2	SET MAXIMUM POSITION.
	LDX	#STRING	SET BLOCKNO = NEW POSITION BLOCKNO.
	LDAB	#BLOCKNO
	JSR	MOVE3BYTES
	JSR	TESTBUF1A	READ CHANNEL INTO BUFFER.
	BEQ	POSBUFPTR	B/ EOF NOT HIT.
	LDX	TBLINDEX	SET BLOCKNO = EOF BLOCK NUMBER (IN I/O
	LDAA	IOBLOCK+4	BLOCK).
	STAA	BLOCKNO,X
	LDAA	IOBLOCK+5
	LDAB	IOBLOCK+6
	STAA	BLOCKNO+1,X
	STAB	BLOCKNO+2,X
	LDAA	CHANSTAT,X	TENTATIVE FILE?
	ANDA	#$70
	CMPA	#$70
	BNE	POSITION$6	B/ NO: DONE.
	BSR	POSBUFPTR1	EXTEND FILE BY (NEWPOSITIONBLOCKNO -
	INC	2,X	BLOCKNO + 1) BLOCKS.
	BNE	POSITION$5
	INC	1,X
	BNE	POSITION$5
	INC	X
POSITION$5	LDX	#DIFFERENCE
	LDAA	CHANNEL
	SWI:EXTEND
	BNE	POSITION$A	B/ FILE CAN'T BE EXTENDED.
	LDX	TBLINDEX
	CLR	EOFFLG,X	CLEAR EOF FLAG.
	LDX	#STRING	SET BLOCKNO = NEWPOSITION BLOCK NUMBER.
	LDAB	#BLOCKNO
	JSR	MOVE3BYTES
	BSR	POSBUFPTR	POSITION BUFFER POINTER.
	LDX	TBLINDEX	SET BUFEND = BUFADR + 1 (I.E. BUFFER
	LDAA	BUFADR,X	SIZE = 256 BYTES).
	INCA
	STAA	BUFEND,X
	RTS		DONE!

POSITION$6	LDAB	#$C	GIVE EOF ERROR
	JMP	ERRORSCAN



* POSITION BUFFER POINTER:

POSBUFPTR	BSR	POSBUFPTR1	SET BUFPTR = NEWPOSITION -
	LDAA	2,X	(BLOCKNO * $100) + BUFADR.
	LDX	STRING
	LDAB	3,X
	LDX	TBLINDEX
	ADDA	BUFADR,X
	STAA	BUFPTR,X
	STAB	BUFPTR+1,X
	RTS
POSBUFPTR1	LDX	#STRING	COMPUTE (NEWPOSITIONBLOCKNO - BLOCKNO).
	LDAB	#BLOCKNO
	JSR	SUB3BYTES
	RTS
* EXIT TO OPERATING SYSTEM.

EXIT$	BSR	RESET$	RESET I/O PACKAGE
	SWI:EXIT	RETURN TO MTS

* RESET THE I/O PACKAGE, CLOSE ALL OPEN CHANNELS AND FLUSH BUFFERS

RESET$	CLR	CLOCKCHANNEL	CLOCK CHANNEL IS CLOSED
	LDAB	#2	CLOSE ANY OPEN CHANNELS (OTHER THAN
	STAB	CHANNEL	CONSOLE).

RESET$1	LDAB	CHANNEL
	CMPB	#MAXCHAN	FINISHED?
	BHI	RESET$3	B/ YES.
	JSR	SETTBLINDEX	GET CHANNEL TABLE INDEX.
	TST	OPENFLAG,X	IS CHANNEL OPEN?
	BEQ	RESET$2	B/ NO.
	JSR	CLOSE$1	YES...CLOSE IT.
RESET$2	INC	CHANNEL	BUMP CHANNEL.
	BRA	RESET$1

RESET$3	LDAA	#-1	ABORT CHANNELS 2-255.
	SWI:ABORT

	LDX	#CHANTBL	ZERO OUT CHANNEL TABLE.
	LDAB	#MAXCHAN*(COLCNT+1)
	JSR	CLRFIELD
	LDAA	#1	GET CONSOLE CHANNEL STATUS,
	SWI:CSTAT
	LDX	#CHANTBL	SET CHANNEL TABLE ENTRIES.
	STAA	CHANSTAT,X
	LDAA	#-1
	STAA	OPENFLAG,X
	LDX	#0	SET ERROR = 0
	STX	SDOSERROR
	CLC
	RTS		DONE.
DEBUG$	LDX	$FFFC	GET THE NMI VECTOR
	DES		DECREMENT STACK POINTER 4 MORE TIMES SO
	DES		IT LOOKS LIKE AN INTERRUPT.
	DES
	DES
	TPA		SAVE USERS CCR
	PSHA		ON STACK
	SEI		IDB EXPECTS INTS OFF
	JMP	0,X	HIT NMI VECTOR


* GET DEBUG CONTROL BYTE.

ATTNCHECK$	EQU	*
	LDX	$FE
	LDAA	$F0
	LDX	SYSVARS,X
	ORAA	8,X	FETCH CONTENTS OF DEBUG CONTROL BYTE,
	CLR	8,X	THEN CLEAR IT.
	TST	KILLFLAG	PROGRAM KILL PROOF?
	BNE	KILPRF1	B/ YES
	STAA	$F0
KILPRF1	RTS

KILLENABL$	CLRA		SET KILL PROOF FLAG OFF
	BRA	KILLPRF

KILLPROOF$	LDAA	#1	SET KILL PROOF FLAG ON
KILLPRF	STAA	KILLFLAG
	CLC
	RTS
	

****************************************
*			*
*			*
*       I/O PACKAGE SUBROUTINES	*
*			*
*			*
****************************************


* SET I/O BLOCK PARAMETERS:

SETIOBLOCK	LDX	TBLINDEX	SET MEMORY ADDRESS,
	LDAA	BUFADR,X
	STAA	IOBLOCK
	CLR	IOBLOCK+1
	LDAA	BUFSIZ	BYTE COUNT,
	STAA	IOBLOCK+2
	CLR	IOBLOCK+3
	LDAA	BLOCKNO,X	AND BLOCK #.
	LDX	BLOCKNO+1,X
	STAA	IOBLOCK+4
	STX	IOBLOCK+5
	RTS


* SET MAXIMUM FILE POSITION:

SETMAXPOS2	LDX	STRING	SET "POSITION" = NEW POSITION.
	STX	SETPOSBLK
	LDX	#SETPOSBLK
	CLRB
	JSR	MOVE4BYTES
SETMAXPOS	LDAB	#MAXPOS	SET MAXPOS = MAX (MAXPOS, POSITION).
	LDX	#CMPMAXPOS
	JSR	SUB4BYTES
	BLS	SETMAXPOS1
	LDX	#CMPMAXPOS
	LDAB	#MAXPOS
	JSR	MOVE4BYTES
SETMAXPOS1	RTS

* SET CHANNEL TABLE INDEX (*** HERE WE ARE LIMITED TO # CHANNELS IN
* I/O PACKAGE WITHOUT CHANGING THIS CODE ***)


SETTBLINDEX	CLRB
	LDAA	CHANNEL
SETTBLINDEX1	DECA
	BEQ	SETTBLINDEX2
	ADDB	#COLCNT+1
	BRA	SETTBLINDEX1
SETTBLINDEX2	LDX	#CHANTBL
	JSR	ADDBX
	STX	TBLINDEX
SETTBL	RTS



* MAKE SURE CHANNEL IS OPEN:

TSTOPEN	LDX	TBLINDEX
	LDAA	CHANSTAT,X	GET CHANNEL STATUS IN ACCA.
	TST	OPENFLAG,X	CHANNEL OPEN?
	BNE	SETTBL	B/ YES.
	LDX	#1032
	JMP	IOERRORX

* CLEAR FIELD POINTED TO BY X-REG FOR NUMBER BYTES IN ACCB

CLRFIELD	CLR	0,X
	INX
	DECB
	BNE	CLRFIELD
	RTS

* MOVE STRING TO COMMAND BUFFER:

MOVECMD	EQU	*
	LDX	#CMDBUF	CLEAR COMMAND BUFFER.
	LDAB	#CMDBUFSIZ	SET LENGTH OF BUFFER


MOVEX	STX	STRING+2	INIT STRING MOVE BLOCK (TO PTR)
	BSR	CLRFIELD
	LDX	SC:PTR
	LDAB	6,X	GET LENGTH
	BNE	MOVERR	LENGTH GREATER THAN 255
	LDAA	7,X	GET LEN LS BYTE
	BEQ	MOVERR	LENGTH = 65K!
	LDX	4,X	GET POINTER TO NAME
	STX	STRING	INIT STRING MOVE BLOCK (FM PTR)
	CMPA	#CMDBUFSIZ/2-1	LONGER THAN 1/2 BUFFER?
			;LEAVE ROOM FOR 2ND SPEC & <CR>
	BCC	MOVERR	B/ YES, GIVE ERROR
	LDX	#STRING	MOVE STRING.
	CLRB		FLAG - TO PTR IN STRING BLOCK
	JSR	MOVE	ACCA = BYTECOUNT
	STX	STRING+2
	LDAA	#$D	WAS LAST BYTE A <CR>?
	DEX
	CMPA	0,X
	BNE	MOVECMD2	B/ NO
	CLR	0,X	YES NULL TERMINATE
	STX	STRING+2	AND DELETE FROM BUFFER
MOVECMD2	RTS
MOVERR	LDAB	#20	GIVE NAME > 16 CHAR ERRORS
	BRA	ERRORSCAN

MOVEQUALS	LDX	STRING+2	MOVE '=' SIGN TO COMMAND BUFFER.
	LDAA	#'=
	STAA	X
	INX
	CLR	0,X	SHOULD NOT NEED AS WE CLRD BUF
	STX	STRING+2
	RTS

* SCAN ERROR TABLE FOR MATCH BETWEEN MTS-6800 AND SOFTWARE DYNAMICS ERROR CODE:

ERRORSCAN	LDX	#ERRTBL	POINT TO ERROR TABLE.
TBLSEARCH	LDAA	X	REACHED END OF TABLE?
	BEQ	FOUND	B/ YES: MATCH NOT FOUND.
	CBA		DOES CURRENT ERROR = THIS TABLE ENTRY?
	BEQ	FOUND	B/ YES, MATCH FOUND.
	INX		BUMP TABLE POINTER TWICE.
	INX
	INX
	BRA	TBLSEARCH	B/ CHECK NEXT ENTRY.
FOUND	LDX	1,X	GET THE CORRESPONDING S.D. CODE.
IOERRORX	EQU	*
	SEC
	LDS	FLAMOUT
	RTS


ERRTBL	FCB	3	?DIRECTORY FULL
	FDB	1015	DISK SPACE EXHAUSTED
	FCB	4	?DISK FULL
	FDB	1015	DISK SPACE EXHAUSTED
	FCB	5	?FILE NOT FOUND
	FDB	1011	NO SUCH FILE
	FCB	6	?DISK TOO FRAGMENTED
	FDB	1015	DISK SPACE EXHAUSTED
	FCB	7	?CHANNEL IS ALREADY OPEN
	FDB	1031	CHANNEL IS ALREADY OPEN.
	FCB	8	?CHANNEL NOT OPEN
	FDB	1032	CHANNEL IS CLOSED
	FCB	9	?PROTECTED FILE
	FDB	1010	FILE IS WRITE PROTECTED
	FCB	10	?INVALID FILE SPEC
	FDB	1009	CAN'T DELETE FILE.
	FCB	11	?PROTECTED FILE
	FDB	1009	FILE IS DELETE PROTECTED
	FCB	12	?END OF FILE
	FDB	1001	END OF FILE ENCOUNTERED
	FCB	15	?CAN'T EXTEND FILE
	FDB	1052	CLUSTER SIZE IS TOO SMALL
	FCB	16	?CAN'T CLEAR BITMAP
	FDB	1006	CAN'T ALLOCATE OR FREE DISK SPACE
	FCB	18	?NON-FILE DEVICE
	FDB	1034	ILLEGAL DEVICE OPERATION REQUESTED
	FCB	17	?INVALID SYNTAX
	FDB	1023	FILE NAME DOESN'T START WITH A-Z
	FCB	20	?SWITCHES NOT ALLOWED
	FDB	1013	LENGTH OF FILE NAME > 16 CHARACTERS
	FCB	22	?SEEK ERROR
	FDB	1047	DISK SEEK ERROR
	FCB	23	?TRACK nnnn SECTOR nnnn, etc.
	FDB	1045	DISK READ ERROR (MAYBE WRITE)
	FCB	24	?INVALID FILE SPEC
	FDB	1021	RENAMED TO FILENAME ISN'T LEGAL
	FCB	25	?PROTECTED FILE
	FDB	1010	FILE IS WRITE PROTECTED
	FCB	26	?NAME ALREADY USED
	FDB	1014	NEW NAME ALREADY EXISTS
	FCB	27	?WRITE PROTECTED FILE
	FDB	1010	FILE IS WRITE PROTECTED
	FCB	29	?WRITE PROTECTED DISK
	FDB	1048	DISK IS WRITE PROTECTED
	FCB	$17	DISK R/W ERROR
	FDB	1045	DISK READ ERROR
	FCB	0	END OF TABLE.
	FDB	100	GENERAL ERROR CODE

* CONVERT HEX TO ASCII AND RETURN IN XREG.  HEX IN ACCA

CNVASCII	TAB		SAVE A COPY
	LSRA
	LSRA
	LSRA
	LSRA
	BSR	CNVASC1	CONVERT HIGH NIBBLE
	STAA	TEMP	SAVE ASCII
	TBA		RESTORE BYTE
CNVASC1	ANDA	#$F	GET LOW NIBBLE
	ADDA	#$90	CONVERT
	DAA
	ADCA	#$40
	DAA
	STAA	TEMP+1
	LDX	TEMP
	RTS

* FOLD SUBROUTINE

FOLD	CMPA	#'a	IF LESS THAN LOWER CASE A
	BCS	FOLD1	B/ NO FOLD
	CMPA	#'z	IF GREATER THAN LOWER CASE Z
	BHI	FOLD1	B/ NO FOLD
	SUBA	#'a-'A	FOLD
FOLD1	RTS


* MOVE UTILITY:

MOVE4BYTES	LDAA	#4
	BRA	MOVE
MOVE3BYTES	LDAA	#3

MOVE	BSR	INITPARS	SET PARAMETERS.
MOVE1	LDX	PAR1
	LDAB	X
	INX
	STX	PAR1
	LDX	PAR2
	STAB	X
	INX
	STX	PAR2	BUMP DESTINATION POINTER.
	DECA		FINISHED?
	BNE	MOVE1	B/ NO.
	RTS

INITPARS	STX	PAR2	SAVE POINTER TO SOURCE/DESTINATION BLOCK.
	LDX	X	SET POINTER TO SOURCE STRING.
	STX	PAR1
	LDX	PAR2
	LDX	2,X	SET POINTER TO DESTINATION STRING.
	TSTB
	BEQ	INITPARS1	B/ DESTINATION ADDRESS ALREADY IN BLOCK.
	LDX	TBLINDEX	DESTINATION = CHANNEL TABLE INDEX + OFFSET
	BSR	ADDBX	IN ACCB.
INITPARS1	STX	PAR2
	RTS



ADDBX	STX	PAR2	X-REG = X-REG + ACCB.
	ADDB	PAR2+1
	STAB	PAR2+1
	BCC	ADDBX1
	INC	PAR2
ADDBX1	LDX	PAR2
	RTS

NAMINDX	LDX	$FC	NAMES ARE SAVED IN PAGE ABOVE JMP TO SIM
	INX		BUMP PAST JMP INST
	INX
	INX
	LDAA	CHANNEL
LOOP	SET	*
	DECA
	BEQ	NAMINDX1	B/ DONE, X @ NAME BUFFER SLOT
	LDAB	#MAXCMDSIZ	EVERY 18 BYTES IS A SAVE NAME BUFFER
	BSR	ADDBX
	BRA	LOOP
NAMINDX1	RTS



* DON'T TRY AND FIGURE OUT HOW THIS WORKS -- YOU MIGHT REGRET IT!

SUB4BYTES	LDAA	#4
	BRA	SUB
SUB3BYTES	LDAA	#3

SUB	BSR	INITPARS	INITIALIZE PARAMETERS.
	CLR	SIGN
	TAB
	DECA
	STAA	SUB2+1	SET OFFSETS FOR INDEXED INSTRUCTIONS.
	STAA	SUB3+1
	STAA	SUB4+1
	CLC
SUB1	LDX	PAR1
SUB2	LDAA	X
	LDX	PAR2
SUB3	SBCA	X	SUBTRACT BYTES.
	LDX	#DIFFERENCE
SUB4	STAA	X
	BEQ	SUB5
	INC	SIGN
SUB5	DEC	SUB2+1	DECREMENT OFFSETS OF INDEXED INSTRUCTIONS.
	DEC	SUB3+1
	DEC	SUB4+1
	DECB
	BNE	SUB1	B/ NOT FINISHED.
	LDAA	SIGN	SET Z-BIT.
	RTS
* BUFFERS AND VARIABLES, ETC:

PWRS10	FDB	10000,1000,100,10
KILLFLAG	FCB	0	KILL ENABLE FLAG - INIT VAL IS OFF.
CRLF	FCB	$D,$A,0	<CR><LF> DATA STRING.
GOXYSTR	FDB	CURPREFIX	ESC CODE TO PREFIX DIRECT CURSOR ADDRESSING
ROWBYTE	FCB	0	SAVE ROW BYTE HERE
COLBYTE	FCB	0	DITTO COL BYTE
	FCB	0	NULL TERMINATE STRING
LOADBUF	FCC	/0,0,/
LOADMAX	RMB	4	COMPUTED IOPKGBASE IN ASCII
LOADELIM	FCB	'/	(FOR SWITCH STRINGS).
CMDBUF	RMB	CMDBUFSIZ	COMMAND BUFFER.
	FCB	0

OPENBLK	FDB	CMDBUF	OPEN BLOCK: BUFFER ADDRESS,
	RMB	2	ADDRESS OF SWITCH LIST,
	FCB	1!$80	MAXIMUM ONE CHANNEL, NO SWITCHES,
	FDB	0	NO DEFAULT EXTENSION.

CREATEFLG	RMB	1	OPEN/CREATE, ASCII/BINARY FLAG.
BINFLG	EQU	CREATEFLG
CHANNEL	RMB	1	CURRENT CHANNEL #.
LMFLG	RMB	1
FLAMOUT	RMB	2	EMERGENCY BAIL-OUT STACK VALUE.
CLOCKCHANNEL	FCB	0	SAVED CLOCK CHANNEL NUMBER

IOBLOCK	RMB	2	BUFFER ADDRESS,
	RMB	2	BYTE COUNT,
	RMB	3	BLOCK #.

POSITION	RMB	4	FILE POSITION (NOT ALWAYS CURRENT).
PAR1	RMB	2	THESE 4 VARIABLES ARE USED BY MOVE
PAR2	RMB	2	AND SUBTRACT SUBROUTINES.
SIGN	RMB	1
DIFFERENCE	RMB	4
TEMP	RMB	2


* DON'T MESS WITH THE ORDER OF THESE VARIABLES!

SETPOSBLK	RMB	2
CMPMAXPOS	FDB	POSITION
	RMB	2
STRING	RMB	2
	RMB	2

ENDIOPKG	EQU	*

	END
