*ABÓ	000°	EFF0
*CODÅ	EFF°	0000
*DATÁ	EFF°	0000
;.DATEº 6/4/82
;.AUTHORº Rogeò W® Chapman
;.titleº Osbornå CP/Í 2.² CBIOÓ Reö 1.4


;*NOTEª   FOÒ USÅ WITÈ OCCTXT6.ASÔ ONLY

;ª	4D2007-0°	MASTEÒ	.ASM
;ª	2D2007-0°	ASSÙ	.ASM
;ª	1D2007-0°	LISTINÇ	.PRN
;ª	4D1007-0°	MASTEÒ	.COM
;ª	2D1007-0°	ASSÙ	.COM

»	+--------------------------+
»	»			   ;
»	»	  Ï Ã Ã		   ;
»	»			   ;
»	»       Ã Â É Ï Ó	   ;
»	»   bù Rogeò W® chapmaî	   ;
»	»			   ;
»	+--------------------------«  

»	Copyrighô 1982® Osborne.

»	Thió producô ió á copyrighô prograí producô oæ 
»	Osbornå anä ió supplieä foò uså witè thå Osborne.
VERS:	=	22

;	LINK	OCCBIO15.ASM	:Jump Table
;	LINK	OCCBIO25.ASM	:Key translation & initialization values
;	LINK	OCCBIO95.ASM	:CP/M disk tables
;	LINK	OCCBIO35.ASM	:ROM call interface
;	LINK	OCCBIO45.ASM	:Non data transfer disk
;	LINK 	OCCBIO55.ASM	:cold and warm boot
;	LINK	OCCBIO65.ASM	:Disk data tranfer I/O
;	LINK	OCCBIO75.ASM	:Utility routines
;	LINK	OCCBIO85.ASM	:Iobyte dispatch table
;	LINK	OCCRAM15.ASM	:Bios ram definitions
;	LINK	OCCRAM25.ASM	:Common ram definitions

MSIZE:	=	59
CCP:	=	0CB00H		;LOCATION CCP
BIOS:	=	CCP+1600H
TRUE	=	0FFH
FALSE	=	NOT TRUE
SI.120	=	55H
BDOS:	=	CCP+806H
CR	=	0DH
LF	=	0AH
CDISK	=	4
IOBYTE	=	3
DBUF	=	80H
ESC	=	1BH
SI.RRD	=	1
ROMVEC	=	100H
VFLO	=	0FFEAH
MRAM	=	0EA80H
ALVS	=	0CH
CSVS	=	20H
LWAMEM	=	0FFFFH

	MSG	'DDT R (RELOCATION VALUE) = ',1FB0H-BIOS
	MSG	'ASSEMBLING BIOS FOR LWA OF ', LWAMEM,'0.'
;	CP/M TO HOST DISK CONSTANTS

HSTSIZ:	=	1024		;BLOCKING/DEBLOCKING BUFFER SIZE
FPYSIB:	=	2048/128	;SECTORS IN FLOPY DSK BLOCK (OSB SD=2K)
FPYDIB:	=	1024/128	;SECTORS IN FLOPY DSK BLCK (OSB DD=1K)

;	CP/M DISK CONTROL BLOCK EQUATES WHICH DEFINE THE 
;	DISK TYPES AND MAXIMUM STORAGE CAPABILITY OF EACH
;	DISK TYPE.

DSKS1:	=	5	;SINGLE DENSITY (256), SINGLE SIDED.
DSKD1:	=	0CH	;DOUBLE DENSITY (1024),SINGLE SIDED.
XEROX:	=	1	;SINGLE DENSITY (128), SINGLE SIDED.
IBM:	=	8	;DOUBLE DENSITY (512), SINGLE SIDED.
DEC:	=	8	;DOUBLE DENSITY (512), SINGLE SIDED.

SIDSM:	=	((40-3)*2*10)/FPYSIB
DIDSM:	= 	((40-3)*8*5 )/FPYDIB
XXDSM:	=	((40-3)*1*18)/FPYDIB
IBMDSM:	=	((40-1)*4*8 )/FPYDIB
DECDSM:	=	((40-2)*4*9 )/FPYDIB

	;	BDOS CONSTANTS ON ENTRY TO WRITE

WRALL:	=	0	;WRITE TO ALLOCATED
WRDIR:	=	1	;WRITE TO DIRECTORY
WRUAL:	=	2	;WRITE TO UNALLOCATED

;	ROM EQUATES.

ENROM:	=	0	;PORT TO ENABLE ROM
DIROM:	=	1	;PORT TO DISABLE ROM

;	MACRO FOR GENERATING CONTROL BLOCKS FOR DISK DRIVES
;	THE FORMAT OF THESE DISK CONTROL BLOCKS ARE AS FOLLOWS:
;	16 BITS = -> TRANSLATION TABLE.
;	48 BITS = WORK AREA FOR CP/M.
;	16 BITS = -> DIRBUF.
;	16 BITS = -> PARAMETER BLOCK.
;	16 BITS = -> CHECK VECTOR.
;	16 BITS = -> ALLOCATION VECTOR.

NDSK:	SET	0	;NUMBER OF DISK DRIVES
NOFDD:	SET	0	;NUMBER OF FOLPPY DISK DRIVES
ALVSZ:	SET	0	;ALLOCATION VECTOR SIZE
CSVSZ:	SET	0	;CHECK VECTOR SIZE

	LIST	M
DPHGEN	MACRO	TYPE,XLATE,DIRBUF,DPBADR
NDSK:	SET	NDSK+1
	DW	%2
	DW	0,0,0
	DW	%3
	DW	%4
	DW	CSV+CSVSZ
	DW	ALV+ALVSZ
NOFDD:	SET	NOFDD+1
CSVSZ:	SET	CSVSZ+(64/4)
ALVSZ:	SET	ALVSZ+((DIDSM+7)/8)
	ENDM

;	MACRO FOR GENERATING THE DISK PARAMETER BLOCKS.
;
;	DISK TYPE DEFINITION BLOCKS FOR EACH PARTICULAR MODE.
;	The format of these areas are as follow:
;	8 bit	= disk type code
;	16 bit	= Sectors per track
;	8 bit	= block shift
;	8 bit	= BS mask
;	8 bit	= Extent mask
;	16 bit	= Disk size/1024-1.
;	16 bit	= Directory size.
;	16 bit	= Allocation for directory.
;	16 bit  = Check area size.
;	16 bit	= Offset to first track.

DPBGEN	MACRO	TYPE,SPT,BSH,BSM,EXM,DSM,DIRSIZ,ALVMSK,OFFSET
	DB	%1
	DW	%2
	DB	%3,%4,%5
	DW	%6-1,%7-1,REV (%8)
	DW	(%7+3)/4
	DW	%9
	ENDM

ALIGN	MACRO	NMBER
	DS	(*+(%1)-1)/(%1)*(%1)-*
	ENDM

;	The following jump table defines the entry points
;	into the CBIOS for use by CP/M and other external
;	routines; therfore the order of these jumps cannot
;	be modified.  The location of these jumps can only
;	be modified by 400h locations, which is a restriction 
;	of MOVCPM.

	ORG	BIOS
 	JMP	CBOOT	;COLD BOOT
	JMP	WBOOT	;WARM BOOT
	JMP	CONST	;CONSOLE STATUS	 (INPUT)
	JMP 	CONIN	;CONSOLE INPUT
	JMP	CONOUT	;CONSOLE OUTPUT
	JMP	LIST	;LIST OUTPUT
	JMP	PUNCH	;PUNCH OUTPUT
	JMP	READER	;READER INPUT
	JMP	HOME	;SET TRACK TO ZERO
	JMP	SELDSK	;SELECT DISK UNIT
	JMP	SETTRK	;SET TRACK
	JMP	SETSEC	;SET SECTOR
	JMP 	SETDMA	;SET DISK MEMORY ADDRESS
	JMP	READ	;READ FROM DISK
	JMP	WRITE	;WRITE ONTO DISK
	JMP	LISTST	;RETURN LST: DEVICE STATUS
	JMP	SECTRN	;SECTOR TRANSLATION ROUTINE

;	EXTENSIONS
RRI:	JMP	ROMRI
	JMP	ROMJMP
FMTJ:	CALL	ROMCDE	;ROM RESIDENT CALL
SBAUD:	CALL	ROMCDE

;	IEEE-488 VECTORS
IEB1C:	CALL	ROMCDE	;CONTROL OUT
IEB2C:	CALL	ROMCDE	;STATUS IN
IEB3C:	CALL	ROMCDE	;GO TO STANDBY
IEB4C:	CALL	ROMCDE	;TAKE CONTROL
IEB5C:	CALL	ROMCDE	;OUTPUT INTERFACE MESSAGE
IEB6C:	CALL	ROMCDE	;OUTPUT DEVICE MESSAGE
IEB7C:	CALL    ROMCDE	;INPUT DEVICE MESSAGE
IEB8C:	CALL	ROMCDE	;PARALLEL POLL

	CALL	ROMCDE	;EXTENSIONS
	CALL	ROMCDE	;   FOR
	CALL	ROMCDE	;       MEMORY-MAPPED VIDEO

	JMP	ACICTL	;HOOK FOR SERIAL COMMAND PORT WRITE
	JMP	ACISTAT	;HOOK FOR SERIAL STATUS PORT READ

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;	This area is reserved data storage area for
;	the set-up program to install printer drivers.
;	function keys, auto boot command, iobyte value,
;	and auto horizontal scroll flag
;						RWC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

IOBITE:	DB	40H	;default to serial printer=40h
			;	parallel printer  =80h
			;  	IEEE   printer	  =ch0h
PRNTER:	DB	00H	;default to standard serial=0
			;Qume		ETX/ACK	=1
			;diablo		XON/XOFF=2
AHSENB:	DB	TRUE	;auto horizontal scroll enable
BRATE:	DB	SI.120	;default baud rate = 1200
SCRSZE:	DB	128	;default screen size = 128
XLTBL:	DW	CNTRL0	;Fixed length table
	DW	CNTRL1	;contains pointer
	DW	CNTRL2	;to strings
	DW	CNTRL3	;to decode
	DW	CNTRL4	;function keys
	DW	CNTRL5
	DW	CNTRL6
	DW	CNTRL7
	DW	CNTRL8
	DW	CNTRL9
	DW	UP
	DW	RIGHT
	DW	DOWN
	DW	LEFT
	DW	EOTBL	;end of table address
IEEEAD:	DB	4	;IEEE device address
PINTFG:	DB	0	;Flag indicates if printer has been initialized
PINIT:	DB	0	;Length of string
	DS	16	;Printer initialization string
ACMD:	DB	1	;auto command  = 0 ignore auto boot
			;	       = 1 auto on cold boot
			;	       = 2 auto on warm boot
			;	       = 3 auto on both
CAUTO:	DB	CAUTOL		;length of auto command here
	DB	'AUTOST '	;auto command goes here
CAUTOL:	=	*-CAUTO-1
INITKB:	DB	03H		;DON'T KNOW WHY BUT IT WAS THERE (D.J. 	
CNTRL0:	DB	'0'		;Variable length table
CNTRL1:	DB	'1'		;is placed her by set-up
CNTRL2:	DB	'2'		;program, with xlttbl
CNTRL3:	DB	'3'		;pointing to the entries
CNTRL4:	DB	'4'	
CNTRL5:	DB	'5'		;Default values for the 
CNTRL6:	DB	'6'		;control numerics
CNTRL7:	DB	'7'		;are the numbers on the keys
CNTRL8:	DB	'8'	
CNTRL9:	DB	'9'
UP:	DB	'K'-40H		;Default values
RIGHT:	DB	'L'-40H		;for the cursor
DOWN:	DB	'J'-40H		;keys are standard
LEFT:	DB	'H'-40H		;values for CP/M
EOTBL:	=	*
	
	ORG	BIOS+256	;space reserved for full function
				;key decoding and 16 byte auto
				;boot command

;	Control Blocks for disk drives
DPBASE:
	DPHGEN	DSKD1,DDXLTS,DIRBUF,DPBD1+1	;Drive A:
	DPHGEN	DSKD1,DDXLTS,DIRBUF,DPBD1+1	;Drive B:
XTAB:	;Translation table addresses
	DW	DDXLTS	;Double density Osborne translation table addres
	DW	XLTS	;Single density Osborne
	DW	XXXLTS	;Xerox translation table address
	DW	IBMXLT	;IBM trAnslation table address
	DW	DECXLT	;DEC translation table address
	DW	XTRXLT	;User defined translation table address
DDXLTS:	=	0	;Translation table for DOUBLE DENSITY OSBORNE 2-1
XLTS:	;Translation table 2 to 1
	DB	0,1,	4,5,	8,9,	12,13,	16,17
	DB	2,3,	6,7,	10,11,	14,15,	18,19
XXXLTS:	;XEROX TRANSLATION TABLE 5 TO 1
	DB	0,	5,	10,	15
	DB	2,	7,	12,	17
	DB	4,	9,	14
	DB	1,	6,	11,	16
	DB	3,	8,	13
IBMXLT:	=	0	;IBM TRANSLATION TABLE, No translation 1 to 1
DECXLT:	;DEC TRANSLATION TABLE 2 TO 1
	DB	0, 1, 2, 3,	8, 9,10,11,	16,17,18,19,	24,25,26,27,	32,33,34,35
	DB	4, 5, 6, 7,    12,13,14,15,	20,21,22,23,	28,29,30,31
XTRXLT:	DS	40	;Space for user defined expansion
;	disk type definition blocks for each particular mode.
DPBSTART:	
		;Start of Disk parameter blocks, used by select disk routine
DPBD1:		;Osborne Double density, single sided
	DPBGEN	DSKD1,8*5 ,3, 7,0,DIDSM ,64,1100000000000000B,3
DPBS1:		;Osborne single density, single sided.
	DPBGEN	DSKS1,2*10,4,15,1,SIDSM ,64,1000000000000000B,3
DPBXD:
	DPBGEN	XEROX,1*18,3, 7,0,XXDSM ,32,1000000000000000B,3
DPBIBM:
	DPBGEN	IBM  ,4*8 ,3, 7,0,IBMDSM,64,1100000000000000B,1
DPBDEC:
	DPBGEN	DEC  ,4*9 ,3, 7,0,DECDSM,64,1100000000000000B,2
DPBXTR:
	DS	16
NUMDPB:	=	(*-DPBSTART)/10H
ROMRI:
;	Exits ROM resident Interrupt routine.
	LD	A,ROMRAM
	MOV	C,A	;PORT
	OT,C	A	;SET ROM OR RAM ENABLED
	POP	IY
	POP	IX
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	LD	SP,IESTK	;reset to interrupt entry stk
	EI
	RET
ROMCDE:
;	Calls ROM resident processor
;	Entry	DE = resident processor to call biased
;		by CBIOS jump vector.
;	NOTE: ROM jump vector must match CBIOS VECTOR
;	Entry at ROMCD1 with low digit of CBIOS vector in reg E
	POP	DE	;Get calling address
	MOV	A,E
	SUI	3
	MOV	E,A
ROMCD1:	LDK	D,high (ROMVEC)
ROMJMP:
;	Entry here to jump to ROM function code directly
;	Entry	DE =ROM jump address
;		BE, HL, IX = any parameters
	PUSH	IY		;Save user Index registers
	PUSH	IX
	DI			;Set up local stack for ROM
	EXX
	LDK	HL,0
	ADD	HL,SP		;Old stack to HL
	LDK	SP,BIOSTK
	PUSH	HL		;Save old stack pointer
	EXX
	CALL	SW2ROM
	CALL	GOROM	;Go to ROM address (DE) and return to next instruction
	CALL	SW2RAM
	POP	IY
	MOV	SP,IY
	POP	IX
	POP	IY
	RET
GOROM:
;	This routine is used to simulate a CALL (DE) instruction
	PUSH	DE	;ROM jump address to IY
	POP	IY
	JMP	[IY]
HOME:
;	Returns disk to home.  This rountine sets the trAck number
;	to zero.  The current host disk buffer is flushed to the
;	disk.
	CALL	FLUSH	;Flush host buffer
	XRA	A
	STO	A,HSTACT
	STO	A,UNACNT
	STO	A,SEKTRK
	STO	A,SEKTRK+1
	RET
SELDSK:
;	Selects disk drive for next transfer.
;	ENTRY	C = Disk selection value (0..15).
;		DE and 1 = 0, first call for this disk.
; 	EXIT	HL = 0, if drive not selectable.
;		HL = DPH address if drive is selected.
	PROC
	PUSH	IX		;Save user IX
	MOV	A,C
	CPI	NDSK
	JNC	SELD		;If invalid drive number
	STO	A,SEKDSK
	MOV	L,C
	MVI	H,0
	ADD	HL,HL		;*2
	ADD	HL,HL		;*4
	ADD	HL,HL		;*8
	ADD	HL,HL		;*16
	MOV	A,E		;get initial bit
	LDK	DE,DPBASE
	ADD	HL,DE		;HL = DPH address
	STO	HL,SAVDPH
	MOV	E,A		;Restore initial bit
	CALL	CHKSEL		;Check to see if density needs to be determined
	JNZ	SELER		;Unable to determine density, error return
	
	LDK	DE,10		;form dpb address
	ADD	HL,DE		;to get type
	LD	E,[HL]		;dpb address in DE
	INC	HL
	LD	D,[HL]	
	DEC	DE
	LD	A,[DE]		;get disk type
	STO	A,SEKTYP	;and store value

	LD	HL,SEQ		;Get current sequence count
	STO	L,[IX+0]
	STO	H,[IX+1]	;Store seq # in LASTA or LASTB

	LD	HL,SAVDPH
	POP	IX		;Restore user IX
	RET
;	Select disk error handling
SELER:	LDK	DE,FORERR
	ANI	1		;Is diskette unformatted?
	JRNZ	SELER1		;YES
	LDK	DE,DENERR	;No, get density error mesage

SELER1:	LD	A,SEKDSK
	ADD	A,'A'
	STO	A,DRV		;Indicate drive in message
	STO	A,DRV1
	CALL	PRINT		;Print appropriate message on console

SELD:	POP	IX		;Restore user IX
	LDK	HL,0
	LDA	CDISK
	SUB	C
	RNZ			;If default drive not in eror
	STO	A,CDISK
	RET

DENERR:	DB	DENL
	DB	CR,LF,'Can''t recognize disk on drive '
DRV:	DS	1
DENL:	=	*-DENERR-1

FORERR:	DB	FORL
	DB	CR,LF,'Unformatted disk on drive '
DRV1:	DS	1
FORL:	=	*-FORERR-1	 
CHKSEL:
;	Determines if noew DPB should be established
;
;	ENTRY	C = disk selection value (0...15)
;		E & D1 = 0, first call for this disk
;	EXIT	IX = address of dirve sequence number
;		Z status bit set, good return
;		Z status bit clear, error return
PROC
	PUSH	HL		;Save user H
	PUSH	BC
	LDK	IX,LASTA	;Get last count for selected drive
	MOV	A,C		;Current drive to A - reg
	ORA	A		;IS THIS DRIVE A?
	JRZ	CHKSEQ		;Yes, check sequence number
	INC	IX		;No, form address for 3
	INC	IX
CHKSEQ:	LD	C,[IX+0]	;Get last sequence number for this drive
	LD	B,[IX+1]
	LD	HL,SEQ		;Get current sequence number
	SBC	HL,BC		;Compare seq #'s
	POP	BC
	PUSH	IX
	BIT	0,E		;First call for this disk?
	JRZ	:10		;Yes, fill in DPB
	MOV	A,H		;No, check elasped time
	ORA	A		;Elasped time < 4 sec
	JRZ	GRET		;Yes, good return
	CPI	02
	JRNC	:10
	MOV	A,L
	CPI	0A0H		;Elasped time > 5 sec
	JRC	GRET		;No, indicate good return
:10:	CALL	GDEN
	JR	RETURN
GRET:	XRA	A
RETURN:	POP	IX
	POP	HL
	RET
GDEN:
;Fills in DPH with appropriate values after determing type and # of sectors
;	ENTRY	SEKDSK = DISK TO SELECT
;	EXIT	A = 0, ZERO FLAG SET .... GOOD RETURN
;		A =-1, ZERO FLAG CLEAR... ERROR RETURN
;	USES ALL REGISTERS
	PROC
	CALL	GETDEN
	JRNZ	SELD1		;Error, unformatted disk
	MOV	A,B		;# OF PHYSICAL SECTORS INTO A
	BIT	2,C		;bits 2 & 3 of reg C indicate sector size
	JRZ	:10		;convert # sectors into # 128 byte sectors
	SLA	A		;A=A*2
:10:	BIT	3,C
	JRZ	:20
	SLA	A
	SLA	A		;A=A*4 OR A=A*8
:20:	LDK	B,NUMDPB	;Number of DPB's to check for 
	LDK	HL,DPBSTART+1	;get dpb address of # logical sectors
	LDK	DE,16		;Next address
	LDK	IX,XTAB		;first translation table address
:LOOP:	CMP	[HL]		;compare # of logical sectors
	JRZ	:30		;match check for same type
:LP1:	INC	IX		;no match increment translation table address
	INC	IX
	ADD	HL,DE		;also get next dpb
	DJNZ	:LOOP		;have we checked all dpb's no go to loop
	JR	SELD2		;Yes, no match error return
:30:	PUSH	AF		;here on match of # of logical sectors
	SHLD	DPB		;save current dpb address
	DEC	HL		;now check type
	MOV	A,C		;value of type returned from getden
	CMP	[HL]		;compare to dpb type
	JRZ	:40		;type is ok
	POP	AF		;number of physical sectors into A reg
	INC	HL		;type does not match
	JR	:LP1		;check next dpb
:40:	POP	AF		;Restore stack
	LD	HL,SAVDPH	;Get header address
	LD	A,[IX+0]	;Get translation table address
	STO	A,[HL]		;Store address in header
	INC	HL
	LD	A,[IX+1]
	STO	A,[HL]
	LDK	DE,9		;Form address in header for DPB
	ADD	HL,DE
	LDK	IX,DPB		;Store DPB address in header
	LD	A,[IX+0]
	STO	A,[HL]
	INX	HL
	LD	A,[IX+1]
	STO	A,[HL]
	XRA	A		;Indicate good return
	RET
;	Error return section
SELD1:	MVI	A,1	;Indicate unformatted disk Z-flag = clear, A = 1
	RET
SELD2:	ORI	02	;Indicate unrecognizable disk Z-flag = clear A = 2
	RET
GETDEN:
;	Gets density of selected disk
;	ENTRY	SEKDSK = Current drive
;	EXIT	C = TYPE	7  6  5  4  3  2  1  0
;				|  |  |  |  |  |  |  |
;		Undef = 0 <-----+--+--+--+  |  |  |  |
;		Bytes/sector <--------------+--+  |  |
;		Sides <---------------------------+  |
;		Density <----------------------------+
;
;	B = # of physical sectors per track
;	A = 0, good return
;	A <> 0, error return
;	Z-bit set, good return
;	Z-bit clear, error return
SENDEN:	=	130H
	PROC
	LD	A,SDISK		;Save urrent value
	STO	A,TEMDSK	;of SDISK
	LD	A,SAVTYP	;And SAVTYP
	STO	A,TEMTYP	;(SDISK & SAVTYP are used by SENDEN1
	LD	A,SEKDSK	;Disk to be select
	STO	A,SDISK		;in SDISK (parameter to SENDEN)
	LDK	DE,SENDEN	;Call SENDEN
	CALL	ROMJMP
	LD	A,TEMDSK	;Restore caller's value of SDISK
	STO	A,SDISK
	LD	A,SAVTYP	;Exit TYPE parameter
	MOV	C,A		;into C - reg
	LD	A,TEMTYP	;Restore caller's SAVTYP
	STO	A,SAVTYP
	RNZ	ERRET		;Error return, flag set by SENDEN
	XRA	A		;Indicate good return
	RET
SETTRK:
;	Sets track number. The track number is saved for later
;	use during a disk transfer operation.
;	ENTRY	BC = track number.
	STO	BC,SEKTRK	;Set track
	LHLD	UNATRK
	MOV	A,L
	XRA	C
	MOV	C,A
	MOV	A,H
	XRA	B
	ORA	C
	RZ			;If same track
;	JMP	CUNACT
CUNACT:
;	Clear Unallocated block count (force pre-reads).
	XRA	A		;A = 0
	STO	A,UNACNT	;Clear unallocated block count
	RET
SETSEC:
;	Set the sector for later use in the disk transfer.  No
;	actual disk operations are performed.
;	Entry  BC = sector number.
	MOV	A,C
	STO	A,TEMSEC	;sector to seek
	RET

SETDMA:
;	Sets Disk memory address for subsequent disk read or 
;	write routines.  This address is saved in DMAADR until
;	the disk transfer is performed.
;	ENTRY	BC = Disk memory address.
;	EXIT	DMAADR = BC.
	STO	BC,DMAADR
	RET
SECTRN:
;	Translates sector number from logical to physical.
;	ENTRY	DE = 0, NO TRANSLATION REQUIRED.
;		DE = Translation table address.
;		BC = sector number to translate.
;	EXIT	HL = translated sector.
	LDA	UNASEC
	CMP	C
	CNZ	CUNACT	;If sectors do not matc
	MOV	A,C
	STO	A,LOGSEC
	MOV	L,C
	MOV	H,B
	MOV	A,E		;Check if translation is required
	ORA	D
	RZ			;None required, return
TRAN:	ADD	HL,DE		;Translation required
	MOV	L,M
	MVI	H,0
	RET
;	B o o t  C P / M  f r o m  d i s k.
;	the CBOOT entry point gets control from the cold start
;	loader and is responsible for the basic system initial-
;	ization.  This includes outputting a sign-on message and
;	initializing the following page zero locations:
;	0,1,2: Set to the warmstart jump vector.
;	    3: Set to the initial IOBYTE value.
;	    4: Default and logged on drive.
;	5,6,7: Set to a jump to BDOS.
;	The WBOOT entry piont gets control when a warm start
;	occurs, a ^C from the console, a jump to BDOS (function
;	0), or a jump to location zero.  The WBOOT routine reads 
;	the CCP and BDOS form the appropriate disk sectors.
;	WBOOT must also re-initialize locations 0,1,2 and 5,6,7.
;	The WBOOT routines exits with the C register set to the 
;	appropriate drive selection value.  Te exit address 
;	is to the CCP routine.

;****************************************************************************
INIT:	PUSH	AF
	LD	A,ROMRAM
	CALL	SW2ROM
	PUSH	AF
	LD	A,INITKB
	STA	2400H		;I THINK ITS THE KEYBOARD (D.J.)
	POP	AF
	CPI	01
	CZ	SW2RAM
	POP	AF
	RET
;***************************************************************************

CBOOT:	LDK 	SP,CCP
	CALL	INIT		;THE STUFF UP ABOVE (D.J.)
	CALL	SW2RAM
	LD	A,IOBITE	;get iobyte value
	STO	A,IOBYTE	;Set I/O byte to default
	LD	A,BRATE
	MOV	C,A
	CALL	SBAUD		;set baud rate
	LDA	SCRSZE
	STA 	LLIMIT		;set screen size
	LD	A,IEEEAD	;Get IEEE device address
	STO	A,IEADR		;and save it in BMRAM
	XRA	A
	STO	A,CDISK		;Set current drive to A
	INC	A
	JR	BCCP		;Do CP/M
WBOOT:	LDK	SP,CCP
	CALL	HOME		;flush any buffer
BCPM:	LDK	DE,ROMVEC+3*1	;Set ROM vector address
	CALL	ROMJMP
	MVI	A,2		;indicate warm boot
BCCP:				;Entry	A = 01, if cold boot
				;	A = 02, if warm boot
	PUSH	AF		;Save entry
	LDK	BC,DBUF		;Set default data transfer address
	CALL	SETDMA
	LDK	HL,HSTBUF
	STO	HL,DMADR	;Set ROM DMA address
;	Clear console control ESC cell
	XRA	A
	STO	A,ESCH		;clear ESC
;	Set-jp low core pointer calls
	LDK	A,0C3H		;Store jumps in low memory
	STO	A,0
	STO	A,5
	LDK	HL,BIOS+3
	STO	HL,1
	LDK	HL,BDOS
	STO	HL,6
	LDK	HL,CAUTO
	POP	BC		;cold/warm indicator in b
	LD	A,ACMD
	AND	B		
	JRZ	DONE
	LD	A,[HL]
	ORA	A
	JRZ	DONE
	LDK	DE,CCP+7
	LDK	B,0
	MOV	C,A
	LDIR			;Move command line to buffer
	LDK	DE,0
	JR	DONE1
SIGNON:	DB	SIGNL		;Length of signon message
	DB	'Z'-40H
	DB	'Osborne Computer System'
	DB	CR,LF
	DB	MSIZE/10+'0',MSIZE mod 10 + '0'
	DB	'k CP/M vers ',VERS/10+'0','.',VERS mod 10 + '0'
	DB	CR,LF,'CBIOS 1.4',CR,LF
SIGNL:	=	*-SIGNON-1
DONE:	LDK	A,2
	CMP	B
	JRZ	DONE0
	LDK	DE,SIGNON
	CALL	PRINT
DONE0:	LDK	DE,3
DONE1:	LDK	HL,CCP
	ADD	HL,DE
	LD	A,CDISK
	MOV	C,A
	JMP	[HL]
READ:
;	a CP/M 128 byte sector.
;	EXIT	A = 0, successful read operation.
;		A = 1, unseccessful read operation.
;		Z bit = 1, successful read operation.
;		Z bit = 0, unsuccessful read operation.
	PROC
	CALL	MVINFO		;Move information for transfer
	XRA	A		;Set flag to force a read
	STO	A,UNACNT	;Clear sector counter
	CALL	FILL		;Fill buffer with data
	POP 	HL
	POP	DE
	LDK	BC,128		;Move 128 bytes
	LDIR
	LD	A,ERFLAG
	ORA	A
	RZ			;If no error
	XRA	A
	STO	A,HSTACT	;Clear host active (A = 0)
	ORI	1		;Indicate error
	RET
WRITE:
;	the seclected 128 byte CP/M sector.
;	ENTRY	C = 0, write to a previously allocated block.
;		C = 1, write to the directory.
;		C = 2, write to the first sector of unallocated
;		data block.
;	EXIT	A = 0, write was successful.
;		A = 1, write was unseccussful.
;		Z bit = 1, write was successful.
;		Z bit = 0, write was unsuccessful.
	PROC
	CALL	MVINFO		;Move information for transfer
	MOV	A,C		;Write type in c
	STO	A,WRTYPE
	CPI	WRUAL
	JRNZ	WRIT2		;If write to allocated
	LD	A,SEKTYP
	CPI	5		;Check for 2K block size
	LDK	A,2048/128
	JRZ	WRIT1		;Type = Osborne single density (2K block)
	LDK	A,1024/128	;Otherwise 1K block size
WRIT1:	STO	A,UNACNT
	LD	HL,SEKTRK
	STO	HL,UNATRK	;UNATRK = SEKTRK
	LD	A,LOGSEC
	INC	A
	JR	WRIT3
WRIT2:	LDK	HL,UNACNT
	LD	A,[HL]
	ORA	A
	JZ	WRIT4		;If no unallocated records
	DEC	[HL]		;Dec unalloc record count
	LDK	HL,DPBASE-16+10	;Get number of sectors per track
	LDK	DE,16		;To point to next DPB
	LD	A,SEKDSK
	MOV	B,A
	INC	B
WRIT25:	ADD	HL,DE
	DJNZ	WRIT25
	LD	E,[HL]
	INC	HL
	LD	D,[HL]
	LD	A,[DE]		;Number of sectors per track in A reg
	MOV	B,A
	LD	A,UNASEC	;Increment logical sector
	INC	A
	CMP	B
	JRNZ	WRIT3		;If not end of track
	LD	HL,UNATRK
	INC	HL
	STO	HL,UNATRK
	XRA	A
WRIT3:	STO 	A,UNASEC
	LDK	A,0FFH
WRIT4:	CALL	FILL
	POP	DE
	POP	HL
	LDK	BC,128
	LDIR
	LDK	A,1
	STO	A,HSTWRT	;HSTWRT = 1
	LD	A,ERFLAG
	ORA	A
	RNZ			;If any errors occured
	LD	A,WRTYPE	;Write type
	CPI	WRDIR		;To directory?
	CZ	FLUSH		;Force write of directory
	LD	A,ERFLAG
	ORA	A
	RET

FILL:
;	Fills host buffer with appropriate host sector.
;	ENTRY	A = 0, Read required if not in buffer.
;		Otherwise read not required.
;	EXIT	On exit the stack will contain the following
;		values:
;		POP	X	:X = host record address.
;		POP	Y	:Y = caller's buffer address.
	PROC
	STO	A,RDFLAG	;Save read flag
	LD	A,SEKTYP
	RRC
	RRC
	ANI	03
	MOV	B,A
	LDK	DE,HSTBUF	;initial offset
	LD	A,SEKSEC	;Get logical sector
	LDK	HL,128		;128 byte records
	JRZ	FILL35		;Jump when sector size <> 128,no deblocking
FILL2:	EX	DE,HL
	RRC
	JRNC	FILL3		;If low bit not set
	ADD	HL,DE		;Add bias to offset
FILL3:	EX	DE,HL
	ADD	HL,HL
	ANI	07FH		;Mask sector
	DJNZ	FILL2
FILL35:	STO	A,SEKSEC	;SEKSEC - physical sector - 1
	LD	HL,DMAADR
	XTHL			;Set return parameters
	PUSH	DE
	PUSH	HL		;Set return address
	LDK 	HL,HSTACT	;host active flag
	LD	A,[HL]
	STO	1,[HL]		;Always becomes 1
	ORA	A
	JRZ	FILL6		;If host buffer inactive
	LDK	HL,HSTTYP
	LD	A,SEKTYP
	CMP	[HL]
	JRNZ	FILL5
	LDK	HL,HSTSEC
	LDK	DE,SEKSEC
	LDK	B,SEKDSK-SEKSEC+1
FILL4:	LD	A,[DE]
	CMP	[HL]
	JRNZ	FILL5		;If mis-match
	INC	HL
	INC	DE
	DJNZ	FILL4		;If all bytes not checked
	RET
FILL5:	CALL	FLUSH		;Flush host buffer
FILL6:	LD	A,SEKDSK	;Move disk
	STO	A,HSTDSK
	STO	A,ACTDSK
	LD	HL,SEKTRK
	STO	HL,HSTTRK
	STO	HL,ACTTRK
	LD	A,SEKSEC
	STO	A,HSTSEC
	STO	A,ACTSEC
	LD	A,SEKTYP
	STO	A,HSTTYP
	STO	A,ACTTYP
	LD	A,RDFLAG
	ORA	A
	RNZ			;If no read required
	LDK	A,0		;Read
	JR	FINAL
FLUSH:
;	Writes out active host buffer onto disk.

	PROC
	LDK	HL,HSTWRT
	LD	A,[HL]
	ORA	A
	RZ			;If host buffer already on disk
	STO	0,[HL]
	LD	A,HSTDSK	;Move disk
	STO	A,ACTDSK
	LD	HL,HSTTRK
	STO	HL,ACTTRK
	LD	A,HSTSEC
	STO	A,ACTSEC
	LD	A,HSTTYP
	STO	A,ACTTYP
	LDK	A,3		;Write flag
;	JMP	FINAL

FINAL:
;	Preforms final transfer processing;
;	ENTRY	A = 0 .. read disk.
;		  = 3 .. write disk.
;	Calls: Rom residen routine to read/write ONE
;		sector only.
	MOV	E,A
	LDK	D,0
	LDK	HL,ROMVEC+3*13
	ADD	HL,DE
	STO	HL,SAVADR
	LDK	HL,ACTSEC
	INC	[HL]		;Update sector+1
	LD	HL,SAVADR
	EX	DE,HL
	LDK	B,1		;Indicate one sector xfer
	CALL	ROMJMP		;Process read or write
	STO 	A,ERFLAG	;Set possible error flag
	RZ			;If no errors
	
	LDK	HL,ERFLAG
	LD	A,[HL]
	ORI	01H
	STO	A,[HL]		;Set error flag
	RET

MVINFO:
;	Move information necessary for transfer;
	XRA	A
	STO	A,ERFLAG	;Clear error flag
	LD	A,TEMSEC
	STO	A,SEKSEC
	RET

PRINT:
;	Print message string to CONSOLE device
	LDK	HL,CONOUT
	JR	STROUT

PSTR:
;	Print message string to LIST device
	LDK	HL,LIST
;	JR	STROUT

STROUT:
;	Print message terminated by zero byte.
;	ENTRY	DE -> message buffer, first byte = length
;	EXIT	DE -> DE + length
;		A = 0.
;		Z bit set.
;	USER A, BC, DE, HL
	PROC
	LD	A,[DE]		;Get a length of print string
	ORA	A
	RZ			;If zero then terminate
	
	MOV	B,A		;Length to B reg
NEXTC:	INC	DE
	LD	A,[DE]		;Get character
	MOV	C,A

	PUSH	DE		;Save print string address
	PUSH	BC		;Save loop counter
	PUSH	HL		;Save output routine address
	LDK 	DE,NEXT
	PUSH	DE		;Return address to stack
	JMP	[HL]		;Output

NEXT:	POP	HL
	POP	BC
	POP	DE
	DJNZ	NEXTC		;Print next character if not done
	RET

;  The following routines will use the IOBYTE to transfer
;  control to the appropriate device drive
CONST:
;	Returns console status
	PROC
	LDK	HL,PTR_CSTAT	;Status table
	JR	GODISPCH	;Call appropriate rtn

CONIN:
;	Reads input character from device
	PROC
	LDK	HL,PTR_CINP	;Table of input rtns
	JR	GODISPCH

CONOUT:
;	Puts output character to device
;	C contains output character
	PROC
	LDK	HL,PTR_COUT	;Table of output rtns

GODISPCH:
	LDK	B,1		;Number of shifts required to align
				;CONSOLE field
	JR	DISPCH

LIST:
;	List device character output
	PROC
	LDK	HL,PINTFG	;Get printer initialiazation flag
	ld	a,[hl]
	ora	a
	jrnz	list1		;Printer previously initialized
	DEC	[HL]		;Non-zero value to PINTFG
	PUSH	BC		;Save character
	INC	HL
	EX	HL,DE		;Get initialization string
	CALL	PSTR		;and print it
	POP	BC		;Restore character

LIST1:	LDK	B,4
	LDK	HL,PTR_LIST	;table of list routines
	JR	DISPCH

PUNCH:
;	Output to punch
	PROC
	LDK	B,6
	LDK	HL,PTR_PNCH	;Punch routines
	JR	DISPCH

READER:
;	Reader input
	PROC
	LDK	B,8
	LDK	HL,PTR_RDR	;reader routines
	JR	DISPCH

LISTST:
;	Return the ready status for the list device.
;	EXIT	A = 0 (zer0), list device is not ready to accept
;		another character.
;		A = FFh (255), list device is ready to accept
;		a character.
	PROC
	LDK	B,4		;Number of left shifts thru carry
				;to align LIST field of IOBYTE
	LDK	HL,PTR_LST	;List status routines
;	JR	DISPCH

DISPCH:
;	on entry here reg B contains the left shift count
;	required to align IOBYTE field to bit 1 posistion.
;	and reg HL contains address of select table
	PROC
	LD	A,IOBYTE

DSPCH1:
	RAL
	DJNZ	DSPCH1
	ANI	6		;Get select field*2
	MOV	E,A
	LDK	D,0		;DE = IOBYTE field * 2
	DAD	DE
	MOV	E,[HL]
	INC	HL
	MOV	H,[HL]		;Get the routine address
	MOV	L,E		;into hl and xchange with pc
	JMP	[HL]

;	Dispatch Table
PTR_CSTAT:
	DW	CNST		;keyboard status
	DW	SISTAT		;serial port input status
	DW	PISTAT		;parallel input status
	DW	IEINSTAT	;status of input device on IEEE Port

PTR_RDR:
PTR_CINP:
	DW	KEYINP		;get input from keyboard
	DW	SPINP		;serial port input
	DW	PARINP		;parallel input
	DW	IEINP		;ieee port input

PTR_PNCH:
PTR_COUT:
	DW	CRTOUT		;output character to crt
	DW	SPOUT		;serial port output
	DW	PAROUT		;parallel output
	dw	ieout		;Ieee port output

PTR_LST:
	DW	CRSTAT
	DW	SOSTAT		;serial output status
	DW	POSTAT		;parallel output status
	DW	IEOSTAT		;ieee output status

PTR_LIST:
	DW	CRTOUT
	DW	PRTOUT
	DW	PAROUT
	DW	IEOUT

CNST:
;	C O N S O L  S T A T U S
;	This routine samples the Console status and returns the
;	following values in the A register.
;	EXIT	A = 0 means no character
;		currently ready to read.
;		A = FFh means character
;		currently ready to read.
;	check if any translated keys are pending
	PROC
	LD	A,COUNT
	ORA	A
	JRNZ	CNST5

;	if no xlated keys pending, check keyhit flag

	LD	A,LKEY		;Get Key hit flag
	ORA	A
	RZ			;If data not available

CNST5:
	ORI	0FFH
	RET

KEYINP:
;	Gets deystroke from ROM deyboard driver.
;	Translates the codes 80h to 8fh as per table.
;	EXIT	A = translated code in ASCII
BASVL0:	=	80H		;lowest value of translatable keys
	PROC
	PUSH	IX		;Save user IX

KIN0:	CALL	AHSCRL
	LDK	HL,COUNT
	LD	A,[HL]		;get number of xlated keys
	ORA	A
	JRZ	KIN10		;if keys pending then
	LD	IX,XLTKEY	;get base address in IX reg	
	LD	A,[IX+0]	;simulate LD A,(ix+COUNT)
COUNT:	=	*-1		;to get next key from table
	INC	[HL]		;Increment count
KRET:	POP	IX		;Restore user IX
	RET

KIN10:
	LDK	E,09
	CALL	ROMCD1

;	When console has returned this code will check
;	for function key and preform some translation

	CPI	80H		;Function keys have value
	JRC	KRET		;80H-8DH
	CPI	8EH		;Do a shift to make pointer
	JRNC	KRET		;into table and return if not function key
	SLA	A
	MOV	E,A
	LDK	D,0
	LDK	IX,XLTBL
	ADD	IX,DE
	LD	L,[IX+0]
	LD	H,[IX+1]
	LD	E,[IX+2]
	LD	D,[IX+3]
	STO	DE,XLTKEY
	SBC	HL,DE
	MOV	A,L
	STO	A,COUNT
	JR	KIN0

AHSCRL;
;	ahscrl - does auto horizontal scroll if required.
	PROC
	LD	A,AHSENB
	OR	A
	RZ

	LD	HL,CURS		;Get cursor
	ADD	HL,HL

;	check for cursor in home window

	LDK	A,100
	CMP	L
	JRC	RHC		;Jump if cursor not in home window
	LD	A,PIAAD		;Check for screen at home
	SUB	VFLO
	RZ			;Screen at home
	XRA	A		;Home screen
	JR	SCRL

RHC:
;	check right-hand margin

	LD	A,PIAAD		;=horizontal screen position
	SUB	VFLO
	ADD	A,100		;Window size*2 (50)
	CMP	L
	JC	:30		;move screen when cursor about to go off
				;the right hand margin

;	check left hand margin

	SUB	90
	CMP	L		;check left margin
	RC			;cursor in window return
	MOV	A,L
	SUB	10
	RZ			;Return if cursor at column 2
	JR	SCRL

:30:	MOV	A,L
	SUB	100

SCRL:	RAR
	ADD	A,' '
	LK	HL,ESCSQ+3
	STO	A,[HL]
	LD	A,PIABD
	AND	1FH
	ADD	A,' '
	DEC	HL
	STO	A,[HL]		;Escsq+2 = vert. coords
	DEC	HL
	DEC	HL		;point to start of esc seq
	LK	B,4

:50:	PUSH	BC
	PUSH	HL
	LD	C,[HL]
	CALL	CRT10
	POP	HL
	POP	BC
	INC	HL
	DJNZ	:50
	RET

ESCSQ:	DB	ESC		;Set screen coord escape sequence
	DB	'S'
	DB	0		;** Y cord
	DB	0		;** X cord

CRSTAT:
;	Returns status of crt.
;	crt is always ready
	PROC
	ORI	0FFH
	RET

CRTOUT:
;	ENTRY	D = output character
EF_ESC:	=	8		;Escape flag bit definitions
EF_GR:	=	1

	PROC
	LD	A,ESCH
	AND	EF_ESC+EF_GR
	JRNZ	CRT10
	MOV	A,C
	CPI	14H
	JRNZ	CRT10
	LD	A,AHSENB
	CMA
	STO	A,AHSENB
	RET

CRT10:
	LDK	E,0CH		;output to crt
	JMP	ROMCD1

SOSTAT:
;	Gets status of output device attached to serial port
	PROC
	LDK	E,2DH
	JR	JMPROM		;Call rom driver

SISTAT:
;	Gets status of input device attached to serial port
	PROC
	CALL 	ACISTAT
	ANI	SI.RRD
	RZ			;return with not ready status
	ORI	TRUE
	RET

SPINP:
;	Inputs a character from the serial port
	PROC
	LDK	E,15H
	JR	JMPROM

SPOUT:
;	Outputs	character in reg c to the serial port (list device)
	PROC
	LDK	E,0FH
	JR	JMPROM

PRTOUT:
;	routine does LIST output and printer protocols
XON:	=	11H
XOFF:	=	13H
ETX:	=	3
ACK:	=	6
	PROC
	CALL	SPOUT
	LD	A,PRNTER
	ORA	A
	RZ	
	ANI	2
	JRNZ	XONXOF
	LDK	A,0DH
	CMP	C
	RNZ

	LDK	C,ETX
	CALL	SPOUT

PRT10:
	CALL	SPINP
	ANI	7FH		;mask out parity bit
	CPI	ACK
	JRNZ	PRT10
	RET

XONXOF:
	CALL	SISTAT
	ORA	A
	RZ
	CALL	SPINP
	ANI	7FH		;mask out parity bit
	CPI	XOFF
	RNZ

PRT20:
	CALL	SPINP
	ANI	7FH		;mask out parity bit
	CPI	XON
	JRNZ	PRT20
	RET

JMPROM:	JMP	ROMCD1

ACICTL:	=	SBAUD
;	Outputs character in c to the ACIA CTL port.

ACISTAT:
;	Returns usart status in A
	PROC
	LDK	E,81H		;Low order byte of ACISTAT routine in ROM
	JR	JMPROM

IEINSTAT:
;	Returns status of IEEE input port
;	EXIT	A = 0 	character not available
;		A = FFH Character available

	PROC
	LDK	E,87H
	JR	JMPROM

IEOSTAT:
;	Returns status of IEEE output port
;	EXIT	A = 0 	transmitter not ready
;		A = FFh transmiter ready
	PROC
	LDK	E,8AH
	JR	JMPROM

IEINP:
;	Reads a character from IEEE port
	LDK	E,8DH
	JR	JMPROM

IEOUT:
;	Outputs the character in reg C to IEEE port
	PROC
	LDK	E,90H
	JR	JMPROM

POSTAT:
;	Gets status of the parallel (centronix) printer
;	attached to the IEEE port
	PROC
	LDK	E,96H
	JR	JMPROM

PISTAT:
;	Gets status of the input device attached to the 
;	parallel port
	PROC
	LDK	E,93H
	JR	JMPROM

PARINP:
;	Inputs a character from parallel port.
	PROC
	LDK	E,99H
	JR	JMPROM

PAROUT:
;	Outputs the character in c to the IEEE port treating the
;	port as a parallel port.
	PROC
	LDK	E,9CH
	JR	JMPROM

SW2ROM:
;	Switches to rom
;	saves all registers
	PROC
	DI
	PUSH	AF
	XRA	A
	OUT	0
STRM:	STO	A,ROMRAM
	POP	AF
	EI
	RET

SW2RAM:
;	Switches to ram
;	preserves all registers
	PROC
	DI
	PUSH	AF
	LDK	A,1
	OUT	1
	JR	STRM		;THIS WAS NEW TOO (D.J)
XXX:	=	*
	IF	XXX > CCP + 1E00H
	ERROR 	SYSTEM SIZE TOO LARGE
	ENDIF
	MSG	'SYSTEM SPACE AVAILABLE = ',1E00H-(XXX-CCP)

	ORG	CCP + 1E00H

LASTA:	DS	4		;used by occoio42, # drives * 2
DPB:	DS	2
SAVDPH:	DS	2
TEMDSK:	DS	1
TEMTYP:	DS	1

SAVADR:	DS	2

ALV:	DS	ALVSZ
CSV:	DS	CSVSZ

SEKTYP:	DS	1
HSTTYP:	DS	1

XLTKEY:	DS	2

YYY:	=	*
	IF	YYY > MRAM
	ERROR	CODE HIT BMRAM
	ENDIF
;OCCRAM2.ASM

;	Used to assemble ROM resident and CBIOS

	ORG	MRAM

;	Host disk xfer buffer and...
;	Format track template holding buffer
HSTBUF:
	DS	1024+128

;	Directory buffer
DIRBUF:	=	HSTBUF+1024

TEM	DS	6
RNDV	=	TEM+1	;random number seed
ERCNT	=	RNDV+1	;DW ERCNT
RTRC	=	ERCNT+2	;retry count
RTRY	=	RTRC+1
MPCHR	DS	1	;prompt character
ECHOP	DS	1	;=0, list echo off
ROMRAM	DS	1	;0= RAM, 1= ROM
DSTSB	DS	6	;Disk staus bytes

;	Disk operation temps and control
DMADR	DS	2	;Address for read/write Disk
DMAADR	DS	2	;CBIOS, users DMA

;	Note order of xxxSEC,xxxTRK,xxxDSK must be maintained
;	along with length (1,2,1).
SEKDEL:	DS	1	;Set for seek=restore command in ROM
			;depends on disk type.  Siemens = 3h, MPI = 0h
SAVSEC	DS	1	;last sector requested
SAVTRK	DS	2	;last track requested
SDISK	DS	1	;Selected disk drive (0,1)
;SAVTYP	=	0EFD0H	;SELECTED TYPE (SECTOR SIZE)

ACTSEC	=	SAVSEC
ACTTRK	=	SAVTRK
ACTDSK	=	SDISK

SEKSEC	DS	1
SEKTRK	DS	2
SEKDSK	DS	1

HSTSEC	DS	1
HSTTRK	DS	2
HSTDSK	DS	1

TEMSEC	DS	1	;Used in bios only
RDFLAG	DS	1	;Read flag
ERFLAG	DS	1	;Error reporting
WRTYPE	DS	1	;Write operation type

;ALV:	DS	ALVS
;CSV:	DS	CSVS

	DS	ALVS
	DS	CSVS 	  			

HSTACT:	DS	1	;host active flag
HSTWRT:	DS	1	;Host written flag
UNACNT:	DS	1	;Unalloc rec count
UNATRK:	DS	2	;Track 
UNASEC:	DS	1	;Sector
LOGSEC:	DS	1	;Logical sector

LDADR	DS	2
KEYLOK	DS	1	;Zero if locked keyboard
CURS	DS	2	;current cursor position

;	Keyboard scan temporaries
TKEY	DS	1	;Tem holding key
HKCNT	DS	1	;Debounce key
LKEY	DS	1	;Last valid keystroke
CKEY	DS	1	;Last control key
ESCH	DS	1	;Esc holding flag

;PIAAD and PIABK must be kept sequential, PIAAD first
;dependency in VC_HOME of BMKEY.asm
PIAAD:	DS	1	;Holds last PIA-A data
PIABD:	DS	1	;Holds last PIA-B data
		
;	Calandar month, day year
IDAY	DS	3
IMONTH	=	IDAY+1
IYR	=	IDAY+2

;	Wall clock time cells and disk active
;	see UPTIM: IN BMKEY.asm
HOURS:	DS	6
MINS:	=	HOURS+1
SECS:	=	HOURS+2
SEC6:	=	HOURS+3

;	Used to deselect drive when there is NO activity 
;	on drive for n seconds.  See FDSK routine
DACTVE:	=	HOURS+4	;=0 by FDSK, Used by UPTIM

BELCNT:	=	HOURS+5	;^S bell timer call

LLIMIT	DS	1	;Max #columns in a ligical line
;	MSG	'LLIMIT = ',LLIMIT,'h.'

;	Disk drive current positions
LDSEL:	DS	2	;Last selected drive
LDTRK:	=	LDSEL+1	;Last track used for non-selected drive

IESTK:	DS	2	;save current stk ptr

;	Interrupt stack
	DS	20*2
ISTK:	DS	0

;	Stack entry
	DS	20*2
BIOSTK:
ROMSTK:	DS	0

ACIAD:	DS	1	;Last command byte written to ACIA

R179x:	DS	4	;179x register save area
KBDLY:	DS	1	;keyboard debounce-delay cell

;since CP/M CANNOT boot off b:, this cell is used 
;to invert the names of the 2 drives:
;	=0, all normal, A=A:, B=B:
;	=1, all inverted, A=B:, B=A:
DSKSWP	DS	1

	ALIGN	10H

SEQ:	=	*-4
ACTTYP:
SAVTYP:	DS	1
RDT_WRTS:  DS	1
CCPADR:	DS	2
KEYLST:	DS	6

SERFLG:	DS	1
IE_ADR:	DS	1
IE_CHAR: DS	1

PIACTL:	DS	1
PP.MODE: DS	1

;	8080 Register Save Area
	ALIGN	10H
REGS:
ESAVE:	DS	1	;E Register save location
DSAVE:	DS	1	;D Register save location
CSAVE:	DS	1	;C Register save location
BSAVE:	DS	1	;B Register save location
FSAVE:	DS	1	;FLAGS save location
ASAVE:	DS	1	;A Register save location
LSAVE:	DS	1	;L Register save location
HSAVE:	DS	1	;H Register save location
PSAVE:	DS	2	;PGM COUNTER save location
SSAVE:	DS	2	;USER STACK pointer save location

BKPA:	DS	2	;last breakpoint address
BKPC:	DS	1	;Contents of bkp

VRTOFF	DS	1	;LAST VERTICAL OFFSET TAKEN FROM COUT
;
;
;	Interrupt Jump Vector is between EFF8, EFFF.
;	Endx	MRAM
				 	
				 	 					 				 			