DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦a63d145aa⟧ TextFile

    Length: 38656 (0x9700)
    Types: TextFile
    Names: »BIOS.ASM«

Derivation

└─⟦0d02879d3⟧ Bits:30004605 COMPAS Pascal version 3.03
    └─ ⟦this⟧ »BIOS.ASM« 

TextFile

;	  CBIOS
;
; COPYRIGHT (C) 1980, 1983 METANIC ApS
;
;    THIS IS THE CBIOS (Custom Basic Input Output System)
; USED WITH CP/M 2.2 ON THE MICRO COMPUTER 'MPS 2001'. THIS
; FILE CONTAINS ALL THE HARDWARE DEPENDENT ROUTINES USED
; BY A RUNNING CP/M 2.0 SYSTEM.
;
;
;

       PSECT   ABS
       ORG     000H



;
; CONSTANTS
;
; CP/M DEPENDENT CONSTANTS

MSIZE	EQU	60		; CP/M VERSION MEMORY SIZE
				;   IN KILOBYTES
;BIAS	 EQU	 .RES.(MSIZE-20)*1024 ; ADDRESS CORRECTION FOR
				;   SYSTEM > 20K
;CCP	 EQU	 3400H+BIAS	 ; BASE ADDRESS OF CCP
;BDOS	 EQU	 CCP+806H	 ; BASE ADDRESS OF BDOS
;BIOS	 EQU	 CCP+1600H	 ; BASE ADDRESS OF BIOS
CDISK	EQU	0004H		; ADDRESS OF CP/M VARIABLE
				;   HOLDING THE CURRENT
				;   DISK NO, 0=A,..,15=P
;NSECTS  EQU	 (BIOS-CCP)/128  ; NUMBER OF SECTORS TO
				;   READ IN DURING A WARM
				;   START

;NSECT1  EQU	 (BIOS-CCP)/512  ; NUMBER OF SECTORS TO
CHARGE	EQU	5400H		 ;   READ IN DURING RESET
BLOWST	EQU	0F000H
; DEBUGGER ADDRESS
ERROR	EQU	0038H

; HARDWARE DEPENDENT CONSTANTS
;
;
;
;
; PORT NUMBERS OF THE KEYBOARD
KBPIOC	EQU	09DH		; PIO CHANNEL A CONTROL
KBPIOD	EQU	09CH		; PIO CHANNEL A DATA
KB89A	EQU	0F9H		; 8910 ADDRESS REG.
KB89D	EQU	0FAH		; 8910 DATA PORT
;
; PORT NUMBERS FOR PIO AND CENTRONIC PRINTER
PIOBC	EQU	9FH		; 03H DISABLES SYNC INTERRUPT
				; 83H ENABLES SYNC INTERRUPT
PIOBD	EQU	9EH		; BIT 0 INPUT HORIZONTAL SYNC
				; BIT 1 OUTPUT CENTRONIC STROBE
				; BIT 2 INPUT
				; BIT 3 INPUT
				; BIT 4 INPUT
				; BIT 5 INPUT INTERRUPT LYSPEN
				; BIT 6 INPUT ENABLE LYSPEN
				; BIT 7 INPUT VERTICAL SYNC
;
; PORT NUMBERS FOR CENTRONICS COMPATIBLE PRINTER
;
LPSP	EQU	PIOBD
LPDP	EQU	0F8H
STROBE	EQU	1
EMPTY	EQU	10H
BUSY	EQU	08
;
;
;
; PORT NUMBERS OF THE CRT
CRTREG	EQU	088H		; CRTC REGISTER SELECTOR
CRTDAT	EQU	089H		; CRTC DATA PORT

; PORT NUMBERS OF THE FLOPPY DISK CONTROLLER
FDCTC	EQU	0C7H		; TERMINAL COUNT PORT
FDCST	EQU	0C0H		; MAIN STATUS PORT
FDCDT	EQU	0C1H		; DATA PORT
FDCDMA	EQU	0C4H		; DMA PORT
FDCMON	EQU	0CAH		; MOTOR ON
FDCMOF	EQU	0C8H		; MOTOR OFF

;
; PORT NUMBERS FOR THE DART AND THE BAUD RATE GENERATOR
;
BAUD0	EQU	8CH		; RATE GENERATOR FOR SERIAL CHANNEL
BAUD1	EQU	8DH		; RATE GENERATOR FOR TAPE RECORDER
BAUD2	EQU	8EH		; 4800 Hz GENERATOR FOR TAPE RECORDER
BAUDC	EQU	8FH		; CONTROL REGISTER
DARTAD	EQU	94H		; SERIAL CHANNEL DATA
DARTAC	EQU	95H		; SERIAL CHANNEL CONTROL
DARTBD	EQU	96H		; TAPE RECORDER DATA
DARTBC	EQU	97H		; TAPE RECORDER CONTROL
;
; PORT NUMBERS FOR THE CTC
;
CTC0	EQU	98H
CTC1	EQU	99H
CTC2	EQU	9AH
CTC3	EQU	9BH

;
; PORT NUMBERS OF MEMORY CONTROL
;
RAMBAW	EQU	0FFH		; BIT 0 - BANK 0 O.S.V.
				; OPENS FOR WRITE ONLY
RAMBAR	EQU	0FEH		; OPENS FOR READ ONLY
				; BIT = 1 -- BANK OPEN
VIDBAN	EQU	0FDH		; OPENS FOR READ AND
				; WRITE.
				; BIT 0 - ROM BANK 0
				; BIT 1 - ROM BANK 1
				; BIT 2 - ROM BANK 2
				; BIT 3 - ROM BANK 3
				; BIT 0-3 READ ONLY
				; BIT 4 - RED BANK MAIN
				; BIT 5 - GREEN BANK
				; BIT 6 - BLUE BANK
				; BIT 7 - FLASH
				; BIT = 1 -- BANK OPEN

SYSBAN	EQU	0FCH		; BIT 7 OPEN AND CLOSE
				; ROM BANK READ ONLY
				; BIT 7 = 0 OPENS

CH80	EQU	0FBH		; BIT 4 = 1 SET 80
				; CHARACTERS/LINE

PIXHO	EQU	640		; PIXELS HORIZONTALLY
PIXVE	EQU	240		; PIXELS VERTICALLY
LINLE	EQU	PIXHO/8 	; LINE LENGTH IN CHARS
				;   IF NOT PROPORTIONAL SPACING
MAXLINESPACE EQU 36		; MAX LINESPACE
MAXSPACEW    EQU 8		; MAX SPACEWIDTH
MAXCHARDIST  EQU 16		; MAX CHARDIST
MASKLEN      EQU (7+MAXCHARDIST+MAXSPACEW+15+7)/8


ESC	EQU	1BH
CR	EQU	0DH
LF	EQU	0AH
CURUP	EQU	0BH
CURRIG	EQU	0CH
CURLEF	EQU	08H
CURHOM	EQU	1EH


; TIME CONSTANTS
SRT	EQU	0EH		; STEP RATE TIME.
				;   CAN BE 1,2,3..16 MS
HUT	EQU	15		; HEAD UNLOAD TIME
				;   CAN BE 0,16,32..240 MS
HLT	EQU	13		; HEAD LOAD TIME
				;   CAN BE 2,4,6..256 MS

; DMA/NON-DMA SELECTION CONSTANT
ND	EQU	1		; NON-DMA (0=DMA)

; DISK FORMAT CONSTANTS
EOT	EQU	0AH		; NO. OF THE LAST SECTOR
				;   ON EACH TRACK
GPL	EQU	07		; GAP LENGTH CONSTANT
DTL	EQU	00		; BYTES PER SECTOR
N	EQU	02		; SECTOR LENGTH INDICATOR


;
; CP/M TO HOST DISK CONSTANTS
;
BLKSIZ	EQU	1024		; CP/M ALLOCATION SIZE
HSTSIZ	EQU	512		; HOST DISK SECTOR SIZE
HSTSPT	EQU	10		; HOST DISK SECTORS/TRK
HSTBLK	EQU	HSTSIZ/128	; CP/M SECTS/HOST BUFFER
CPMSPT	EQU	HSTBLK*HSTSPT	; CP/M SECTORS/TRACK
SECMSK	EQU	HSTBLK-1	; SECTOR MASK

;
; BDOS CONSTANTS ON ENTRY TO WRITE
;
WRALL	EQU	0		; WRITE TO ALLOCATED
WRDIR	EQU	1		; WRITE TO DIRECTORY
WRUAL	EQU	2		; WRITE TO UNALLOCATED

; DELAY CONSTANT USED IN COMMAND AND READRESULT
DELAYCNT EQU	40H

; MAXIMUM NUMBER OF RE-READS/RE-WRITES
MAXREPEATS EQU	10
;
; RAM AREA FILLED WITH DATA AFTER RESET
;

;
; ORIGIN
;
	ORG	0000H		; START ADDRESS IN ROM

STARTC:
	LD	SP,DIRBF+50	; SET STAK. CP/M NOT RUNNING
	LD	A,0FFH
STA3:	DEC	A
	JR	NZ,STA3
	LD	(SYBAN),A
	LD	(RAMRD),A	; SET BANK VARIABLES
	LD	(RAMWR),A
	LD	(VIDROM),A
	LD	(INSAVE),A
	LD	HL,BLOWUP
	LD	DE,BLOWST
	LD	BC,ASCTAB-BLOWUP
	LDIR
	CALL	INTINI
	CALL	CRTINI
	CALL	CTCINI
	CALL	PIOINI
	CALL	DARINI
	LD	A,(SNR)
	LD	(SNR1),A
	LD	A,(SNR+2)
	LD	(SNR1+1),A
	LD	A,(SNR+3)
	LD	(SNR1+2),A
START1: LD	HL,FUNCST
	LD	DE,FBUF
	LD	BC,FUNCS1-FUNCST
	LDIR
	LD	HL,MSGC 	; SAY HELLO
	CALL	OUTTX
STAR5:	EI			; START INTERRUPT
	CALL	CONIN		; READ KEYBOARD
;	 DI
	CP	27
	JP	Z,CONFIG
	CP	0DH
	JR	NZ,STAR5
	LD	C,A		; C := A
	CALL	CONOUT		; ECCO
STAR6:	LD	C,0AH		; SEND LF
	CALL	CONOUT
CPM:
STAR10: CALL	READRESULT	; CLEAR  765
	LD	A,01
	OUT	(RAMBAW),A	; OPEN RAM FOR WRITE
	LD	(RAMWR),A
	XOR	A
	LD	(CDISK),A
	LD	(HSTACT),A
	LD	(UNACNT),A
	LD	(SEKDSK),A
STAR11: CALL	MOTORS
	LD	HL,SPECIO+OFFSET
	CALL	COMMAND
	CALL	STAR12
	JR	STAR15
STAR12: XOR	A
	LD	(HSTDSK),A
	LD	(SEEKTR+OFFSET),A
	LD	(SEEKNO+OFFSET),A
	LD	(RECANO+OFFSET),A
	LD	(RDTR+OFFSET),A
	LD	(RDTR+OFFSET+1),A
	LD	(RDNO+OFFSET),A
	CALL	HOME
	XOR	A
	LD	(DISKNO),A
	LD	(HSTTRK),A
	LD	(HSTTRK+1),A
	RET
STAR15: LD	BC,100H 	; READ CP/M INTO 100H
	LD	A,10
	LD	(RDEOT+OFFSET),A
	DI
	CALL	RTRACK		; READ TRACK ZERO
	EI
	OR	A
	JR	NZ,STAR17	; NOT METANIC OR HH
	LD	DE,HSTBUF	; CHECK FORMAT ROUTINE
	LD	HL,STAR30
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,100H 	;
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	CP	0C3H		; METANIC FORMAT?
	JR	Z,READ96
	LD	HL,100H+512
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	CP	0C3H		; HH FORMAT
	JP	Z,READ97
	LD	HL,TEXT6
	CALL	OUTTX
	JP	START1
STAR17:
	LD	A,02		; MOVE HEAD TO TRACK 1
	LD	(SEEKTR+OFFSET),A
	LD	HL,SEEKCO+OFFSET
	CALL	COMMAND
	CALL	ENDSEEK 	;
	LD	A,01		; UPDATE VARIABLES
	LD	(RDTR+OFFSET),A
	LD	A,09
	LD	(RDEOT+OFFSET),A
	LD	BC,100H 	; READ CP/M INTO 100H
	DI
	CALL	RTRAC1
	EI
	OR	A
	JP	NZ,STAR10
	LD	HL,STAR30
	LD	DE,HSTBUF
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,100H 	; CHECK FOR SYSTEM
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	CP	0C3H
	JP	Z,READ98	; SYSTEM OK. PROCEED
	LD	HL,TEXT6	; NO SYSTEM. TELL USER
	CALL	OUTTX		; AND GO BACK.
	JP	START1
READ96: INC	HL		; FIND START OF CCP
	INC	HL
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	SUB	03
	LD	(CCPSTO+1),A
	LD	B,A
	CALL	CPMSIZ
	XOR	A
	LD	(CCPSTO),A
	LD	A,1		; READ TRACK 1
	LD	(RDTR+OFFSET),A
	LD	(RDTR+1+OFFSET),A
	LD	A,4
	LD	(RDNO+OFFSET),A
	LD	BC,100H+512*10
	DI
	CALL	RTRACK		; READ REST
	EI
	LD	HL,100H+512*11	; SECTOR 12 AND SECTOR 13
	CALL	HSTBUF		; FIRST INITIALIZATION
	LD	A,B		; PROGRAM
	OR	A
	CALL	Z,INIT1
	LD	HL,STAR40
	LD	DE,HSTBUF
	LD	BC,STAR50-STAR40
	LDIR
	LD	HL,100H
	LD	DE,(CCPSTO)
	LD	BC,512*11
	CALL	HSTBUF		; (STAR40)
	XOR	A
	LD	(DISKFO+OFFSET),A
	LD	HL,DPBLK0+OFFSET
	LD	(DPBAS0+OFFSET+10),HL
	LD	DE,DIRBF
	LD	HL,STAR30
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,100H+512*19
	CALL	DIRBF
	LD	A,B
	OR	A
	JP	NZ,GOCPMC
	LD	HL,STAR40
	LD	DE,DIRBF
	LD	BC,STAR50-STAR40
	LDIR
	LD	HL,100H+512*19	; MOVE INIT.SECTOR
	LD	DE,HSTBUF
	LD	BC,512
	CALL	DIRBF
	LD	A,(HSTBUF+3)	; TEST FOR DISK FORMAT
	OR	A
	JR	NZ,INI1
	LD	HL,HSTBUF+11H
	LD	DE,DISKFO+1+OFFSET
	LD	BC,7
	LDIR
	LD	HL,DISKFO+1+OFFSET
	LD	B,3
	LD	C,0		; DISK NO
R0:	INC	C
	PUSH	BC
R1:	LD	A,(HL)
	INC	HL
	OR	A
	JR	Z,R1A		; NOTHING TO MOVE
	PUSH	HL		; SAVE ADDRESS IN DISKFO
	LD	HL,DPBLK0+OFFSET
	LD	DE,DPBLK1-DPBLK0
R2:	ADD	HL,DE		; CALCULATE ADDRESS
	DEC	A
	JR	NZ,R2
	PUSH	HL		; SAVE ADDRESS DPBLK?
	LD	HL,DPBAS0+OFFSET
	LD	DE,DPBAS1-DPBAS0
	LD	B,C
R3:	ADD	HL,DE
	DEC	C
	JR	NZ,R3
	LD	C,B
	LD	DE,10
	ADD	HL,DE
	POP	DE		; RECOVER ADDRESS DPBLK?
	LD	A,E
	LD	(HL),A
	INC	HL
	LD	A,D
	LD	(HL),A
	POP	HL		; RECOVER ADDRESS IN DISKFO
R1A:	POP	BC		; RECOVER COUNTER
	DJNZ	R0
INI1:	LD	A,(HSTBUF+20H)
	OR	A
	JR	NZ,INI2
	LD	BC,(HSTBUF+21H)
	LD	A,00110100B
	OUT	(BAUDC),A
	LD	A,C
	OUT	(BAUD0),A
	LD	A,B
	OUT	(BAUD0),A
INI2:
	LD	A,(HSTBUF+1)
	CP	40
	JR	NZ,INI2A
	LD	HL,TX7
	CALL	OUTTX
	JR	INI3
INI2A:	CP	80
	JR	NZ,INI3
	LD	HL,TX8
	CALL	OUTTX
INI3:
	LD	A,(HSTBUF+2)
	OR	A
	JR	NZ,INI5
	LD	HL,HSTBUF+80
	LD	DE,FBUF
	LD	BC,80H
	LDIR
INI5:
	LD	HL,INI8
	PUSH	HL
	LD	A,(HSTBUF+6)
	CP	'N'
	JR	NZ,INI6
	JR	INISER
INI6:	CP	'U'
	JR	NZ,INI7
	JR	INISER
INI7:	CP	'L'
	JR	NZ,INI7A
	JR	INISER
INI7A:	POP	HL
INI8:
	LD	HL,INI10
	PUSH	HL
	LD	A,(HSTBUF+7)
	CP	'O'
	JR	NZ,INI9
	JR	INISER
INI9:	CP	'S'
	JR	NZ,INI9A
	JR	INISER
INI9A:	POP	HL
INI10:	LD	HL,INI12
	PUSH	HL
	LD	A,(HSTBUF+8)
	CP	'0'
	JR	NZ,INI11
	JR	INISER
INI11:	CP	'1'
	JR	NZ,INI11A
	JR	INISER
INI11A: POP	HL
INI12:	LD	A,(HSTBUF+9)
	CP	0
	JR	Z,INI12A
	CP	1
	JR	Z,INI12A
	JR	INI13
INI12A: LD	(PRINTE),A
	LD	A,(HSTBUF+10)
	OR	A
	JR	NZ,INI13
	LD	A,(HSTBUF+11)
	LD	(MODE),A


INI13:
	LD	A,(HSTBUF+4)	; TEST FOR START PROGRAM
	OR	A
	JR	NZ,INI14
	LD	A,(HSTBUF+80+80H)
	INC	A
	LD	C,A
	LD	B,0
	LD	HL,(CCPSTO)
	LD	DE,7
	ADD	HL,DE
	EX	DE,HL
	LD	HL,HSTBUF+80+80H
	DI
	LD	A,01
	OUT	(RAMBAW),A
	LD	(RAMWR),A
	LDIR
	XOR	A
	LD	(DE),A
INI14:
	LD	A,(HSTBUF+5)
	LD	(TASTBU),A
	JP	GOCPMC
INISER: PUSH	AF
	LD	C,27
	CALL	CONOUT
	LD	C,'b'
	CALL	CONOUT
	POP	AF
	LD	C,A
	CALL	CONOUT
	RET

TX7:	DEFB	27,'4',0
TX8:	DEFB	27,'8',0
READ97: 			; HH FORMAT
	INC	HL
	INC	HL
	CALL	HSTBUF		; STAR30
	LD	A,B
	SUB	03
	LD	(CCPSTO+1),A
	LD	B,A
	CALL	CPMSIZ
	XOR	A
	LD	(CCPSTO),A
	LD	A,02
	LD	(SEEKTR+OFFSET),A
	LD	HL,SEEKCO+OFFSET
	CALL	COMMAND
	CALL	ENDSEEK
	LD	A,01
	LD	(RDTR+OFFSET),A
	LD	BC,100H+512*10
	DI
	CALL	RTRACK
	EI
	LD	HL,STAR40
	LD	DE,HSTBUF
	LD	BC,STAR50-STAR40
	LDIR
	LD	HL,100H+512
	LD	DE,(CCPSTO)
	LD	BC,512*11
	CALL	HSTBUF		; STAR40
	LD	A,1
	LD	(DISKFO+OFFSET),A
	LD	HL,DPBLK1+OFFSET
	LD	(DPBAS0+OFFSET+10),HL
	JP	GOCPMC
READ98: INC	HL		; FIND SIZE OF SYSTEM
	INC	HL
	CALL	HSTBUF		; (STAR30)
	LD	A,B		; HIGH BYTE IN B
	SUB	3		; REMOVE OFFSET
	LD	(CCPSTO+1),A	; STORE FOR LATER
	LD	B,A
	CALL	CPMSIZ	      ; TELL THE USER THE SYSTEM SIZE
	XOR	A		; SET LOW BYTE OF SYSTEM
	LD	(CCPSTO),A
	LD	A,04		; MAKE READY FOR READING 2. TRACK
	LD	(RDNO+OFFSET),A ; SIDE 1
	LD	A,01		; TRACK 1
	LD	(RDTR+OFFSET),A
	LD	(RDTR+OFFSET+1),A ; HEAD 1
	LD	BC,100H+512*9	; NEXT MEMORY POSITION
	DI
	CALL	RTRAC1		; READ REST (2 SECTORS ONLY VALID)
	EI
	OR	A
	JP	NZ,ERROR
	LD	HL,STAR50	; MAKE READY TO MOVE INTO POSITION
	LD	DE,HSTBUF
	LD	BC,STAR70-STAR50
	LDIR			; BLOW THE ROUTINE INTO HSTBUF
	CALL	HSTBUF		; CALL STAR50
	LD	A,02		; SET DISK FORMAT
	LD	(DISKFO+OFFSET),A
	LD	HL,DPBLK2+OFFSET
	LD	(DPBAS0+OFFSET+10),HL
	JP	GOCPMC		; START CP/M
STAR30: DI
	LD	A,80H
	OUT	(SYSBAN),A	; CLOSE ROM
	LD	A,01
	OUT	(RAMBAR),A	; OPEN RAM FOR READ
	LD	A,(HL)
	LD	B,A
	XOR	A
	OUT	(RAMBAR),A	; CLOSE RAM
	OUT	(SYSBAN),A	; OPEN ROM
	EI
	RET
STAR40:
	LD	A,80H		; CLOSE ROM
	OUT	(SYSBAN),A
	LD	A,01
	OUT	(RAMBAR),A	; OPEN RAM FOR READ AND
	OUT	(RAMBAW),A
	LDIR
	XOR	A
	OUT	(RAMBAR),A	; CLOSE RAM
	OUT	(RAMBAW),A
	OUT	(SYSBAN),A	; OPEN ROM
	RET
STAR50:
	LD	A,80H		; CLOSE SYSTEM BANK
	OUT	(SYSBAN),A
	LD	A,01		; OPEN RAM FOR READ
	OUT	(RAMBAR),A	; AND WRITE
	OUT	(RAMBAW),A
	XOR	A		; COUNTER
	LD	DE,(CCPSTO)	; START OF CCP
STAR55: LD	HL,STAR60-STAR50+HSTBUF ; SKEW TABLE
	LD	B,0		; BC := A
	LD	C,A
	ADD	HL,BC		; START OF TABLE+ACTUAL ENTRY
	PUSH	AF		; SAVE AF
	LD	A,(HL)		; GET ACTUAL SECTOR
	LD	B,A		; MOVE TO B
	POP	AF		; RECOVER AF
	LD	HL,100H-512	; OFFSET FOR HL
	PUSH	DE		; SAVE DE
	LD	DE,512		; SIZE OF SECTOR
STAR57: ADD	HL,DE		; CALCULATE ADDRESS
	DJNZ	STAR57		; UNTIL B := 0
	POP	DE		; DESTINATION ADDRESS
	LD	BC,512		; SIZE OF SECTOR
	LDIR			; MOVE
	INC	A		; MAKE READY FOR NEXT SECTOR
	CP	09H		; LAST ON SIDE 0
	JR	NZ,STAR55	; NO
	LD	HL,100H+512*9	; MOVE FIRST SECTOR ON SIDE 1
	LD	BC,512		; SIZE
	LDIR
	LD	HL,100H+512*11	; MOVE SECOND SECTOR
	LD	BC,512		; SIZE
	LDIR
	XOR	A		; OPEN SYSTEM AND CLOSE
	OUT	(RAMBAW),A
	OUT	(RAMBAR),A
	OUT	(SYSBAN),A
	RET
STAR60:

STAR70:
CPMSIZ: PUSH	BC
	LD	C,0DH
	CALL	CONOUT
	LD	C,0AH
	CALL	CONOUT
	POP	BC
	LD	A,B
	RRCA			; /2
	RRCA			; /4
	ADD	A,07		; CALCULATE CP/M SIZE
	LD	B,0
CPMS10: SUB	10
	JR	C,CPMS20
	INC	B
	JR	CPMS10
CPMS20: PUSH	AF
	LD	A,B
	ADD	A,30H
	LD	C,A
	CALL	CONOUT
	POP	AF
	ADD	A,3AH
	LD	C,A
	CALL	CONOUT
	LD	HL,MSGC3
	JP	OUTTX
RTRAC1: LD	HL,READ9
	PUSH	HL
	LD	H,B
	LD	L,C
	LD	BC,512*9	; NO OF BYTES
	JR	STAR19
RTRACK: LD	HL,READ9
	PUSH	HL
	LD	H,B
	LD	L,C
	LD	BC,512*10	; NO OF BYTES
STAR19: LD	D,0A0H
	EXX
	LD	HL,READTR+OFFSET
	CALL	COMMAND 	; READ TRACK ZERO
	EXX
STAR20:
	IN	A,(FDCST)
	AND	D
	JP	P,STAR20
	RET	PO
	IN	A,(FDCDT)
	LD	(HL),A
	INC	HL
	DEC	BC
	LD	A,B
	OR	C
	JP	NZ,STAR20
	RET
READ9:	OUT	(FDCTC),A
	CALL	READRESULT	; READ OK
	LD	HL,RESULT
	LD	A,(HL)
	CP	7
	JP	NZ,STAR11
	INC	HL
	LD	B,2
	LD	A,(HL)
	AND	11111000B
READ95: INC	HL
	OR	(HL)
	DJNZ	READ95
	RET	Z		; READ OK
	LD	A,0FFH
	RET
OUTTX:	LD	A,(HL)
	OR	A
	RET	Z
	LD	C,A
	PUSH	HL
	CALL	CONOUT
	POP	HL
	INC	HL
	JR	OUTTX
CONFIG:
	EI
	CALL	READRESULT
	CALL	MOTORS
	LD	HL,SPECIO+OFFSET
	CALL	COMMAND
	CALL	STAR12
	LD	A,1
	LD	(HSTTRK),A
	LD	(HEADNO+OFFSET),A
	LD	A,10
	LD	(SECTOR),A
	LD	A,46H
	LD	(IOCMD+OFFSET),A
	XOR	A
	LD	(HSTDSK),A
	CALL	IOSEC
	OR	A
	JR	Z,CONF01
	LD	HL,TX6
	CALL	OUTTX
	LD	HL,TX6A
	CALL	OUTTX
	JP	START1
TX6:	DEFB	0DH,0AH,27,'I'
	DEFM	'INITIALISERINGSSEKTOR KAN IKKE '
	DEFB	0
TX6A:	DEFM	'LÆSES!'
	DEFB	27,'i'
	DEFB	0DH,0AH,0
CONF01: LD	A,(HSTBUF+2)
	OR	A
	JR	NZ,CONF02
	LD	HL,HSTBUF+80
	LD	DE,FBUF
	LD	BC,80H
	LDIR
CONF02: LD	HL,MSGC1
	CALL	OUTTX
	CALL	CONIN
	LD	C,A
	PUSH	AF
	CALL	CONOUT
	POP	AF
	CP	31H		; TEST FOR DISK FORMAT
	JP	Z,CONF10
	CP	32H		; TEST FOR TIME SET
	JP	Z,CONF20
	CP	33H
	JP	Z,CONF30	; SET SERIAL CHANNEL
	CP	34H
	JP	Z,CONF40
	CP	35H		; SET FUNCTION KEYS
	JP	Z,FUNTA
	CP	36H
	JP	Z,AUTOST	; AUTOSTART PROGRAM
	CP	37H
	JP	Z,TASBUF
	CP	38H
	JP	Z,VALGPR
	CP	39H
	JP	Z,SLETIN	; CLEAR INISECTOR
	CP	0DH
	JP	Z,CONF05
	JR	CONF01
CONF05:
	LD	HL,MSGC2
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	AND	01011111B
	CP	'J'
	JR	Z,CONF06
	CP	'N'
	JR	NZ,CONF05
CONF03: LD	C,27
	CALL	CONOUT
	LD	C,'*'
	CALL	CONOUT
	JP	START1
CONF06: XOR	A
	LD	(HSTBUF),A	; INIT.SECTOR ACTIVE
	CALL	MOTORS
	LD	HL,SPECIO+OFFSET
	CALL	COMMAND
	CALL	STAR12
	LD	A,1
	LD	(HSTTRK),A
	LD	(HEADNO+OFFSET),A
	LD	A,10
	LD	(SECTOR),A
	LD	A,45H
	LD	(IOCMD+OFFSET),A
	XOR	A
	LD	(HSTDSK),A
	CALL	IOSEC
	OR	A
	JR	Z,CONF03
	LD	HL,TX6
	CALL	OUTTX
	LD	HL,TX3
	CALL	OUTTX
	JP	START1
TX3:
	DEFM	'SKRIVES!'
	DEFB	27,'i',0DH,0AH
	DEFB	0
CONF10: LD	HL,TEXT3
	CALL	OUTTX
	CALL	CONIN		; GET FORMAT
	PUSH	AF		; SAVE FORMAT
	LD	C,A
	CALL	CONOUT		; TELL THE USER
	POP	AF		; RECOVER FORMAT
	AND	00000011B
	DEC	A		; NOW 0 := METANIC
				;     1 := 40 TRACK SINGLE
				;     2 := 40 TRACK DUAL
	PUSH	AF		; SAVE FORMAT
	LD	HL,TEXT4
	CALL	OUTTX
	CALL	CONIN		; GET DISK NO
	PUSH	AF		; SAVE DISK NO
	LD	C,A
	CALL	CONOUT		; TELL THE USER
	POP	AF		; RECOVER DISK NO
	AND	00000011B	;
	LD	C,A		; C := DISK NO
	LD	HL,DISKFO+OFFSET
	LD	E,A
	LD	D,0
	ADD	HL,DE
	POP	AF		; RECOVER FORMAT
	LD	(HL),A		; SAVE IN TABLE
	LD	B,A		; B := FORMAT
	LD	A,C
	LD	HL,DPBAS0+OFFSET
	LD	DE,DPBAS1-DPBAS0
	OR	A
CONF14: JR	Z,CONF12
	ADD	HL,DE
	DEC	A
	JR	CONF14
CONF12: LD	DE,10
	ADD	HL,DE
	PUSH	HL
	LD	HL,DPBLK0+OFFSET
	LD	DE,DPBLK1-DPBLK0
	LD	A,B
	OR	A
CONF18: JR	Z,CONF16
	ADD	HL,DE
	DEC	A
	JR	CONF18
CONF16: EX	DE,HL
	POP	HL
	LD	A,E
	LD	(HL),A
	INC	HL
	LD	A,D
	LD	(HL),A
	LD	HL,TEXT5
	CALL	OUTTX
	CALL	CONIN
	AND	01011111B
	CP	01001010B
	JR	Z,CONF10
	XOR	A
	LD	(HSTBUF+3),A  ; DISK FORMAT TABLE ACTIVE
	LD	HL,DISKFO+OFFSET
	LD	DE,HSTBUF+10H
	LD	BC,8
	LDIR
	JP	CONF01
CONF20: LD	HL,TX1		; SET TIME
	CALL	OUTTX
	LD	HL,TIMBUF+OFFSET
	LD	B,12
	XOR	A
CONF21: LD	(HL),A
	INC	HL
	DJNZ	CONF21
	LD	HL,TIMBUF+OFFSET
	LD	B,12
CONF22: PUSH	HL		; SAVE TIMBUF
	PUSH	BC		; SAVE B
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	CP	0DH
	JR	Z,CONF24
	CP	'-'
	JR	Z,CONF23
	CP	30H
	JR	C,CONF29
	CP	3AH
	JR	NC,CONF29
CONF23: POP	BC
	POP	HL
	LD	(HL),A
	INC	HL
	DJNZ	CONF22
	PUSH	HL
	PUSH	BC
CONF24: POP	BC
	POP	HL
	LD	HL,TIMBUF+OFFSET
	CALL	CONF25
	LD	(HOUR),A
	LD	HL,TIMBUF+3+OFFSET
	CALL	CONF25
	LD	(MINUTE),A
	LD	HL,TIMBUF+6+OFFSET
	CALL	CONF25
	LD	(SECOND),A
CON24:	LD	HL,TX2
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	AND	01011111B
	CP	'J'
	JR	Z,CONF28
	CP	'N'
	JR	Z,CON28
	JR	CON24

CONF28: LD	A,0FFH
	LD	(VISF),A
	JP	CONF01
CON28:	XOR	A
	LD	(VISF),A
	JP	CONF01

CONF25: LD	A,(HL)
	SUB	30H
	OR	A
	LD	B,A
	JR	Z,CONF27
	LD	A,0
CONF26: ADD	A,10
	DJNZ	CONF26
	LD	B,A
CONF27: INC	HL
	LD	A,(HL)
	SUB	30H
	ADD	A,B
	RET


CONF29: POP	BC
	POP	HL
	JP	CONF20
TX1:	DEFB	27,'*'
	DEFB	0DH,0AH,0AH
	DEFM	'Angiv tiden på formen: TT-MM-SS'
	DEFB	0DH,0AH
	DEFM	'afslut med RETURN'
	DEFB	0DH,0AH
	DEFM	'? '
	DEFB	0
TX2:	DEFB	0DH,0AH,0AH
	DEFM	'Skal tiden vises (J/N) ? '
	DEFB	0
CONF30: LD	HL,TX4		; SET SERIAL CHANNEL
	CALL	OUTTX
CONF31: CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	CP	32H
	JP	C,CONF39
	CP	3AH
	JP	NC,CONF39
	SUB	30H
	ADD	A,A
	LD	HL,BAUDTA
	LD	C,A
	LD	B,0
	ADD	HL,BC
	LD	A,00110100B
	OUT	(BAUDC),A
	LD	A,(HL)
	LD	C,A
	OUT	(BAUD0),A
	INC	HL
	LD	A,(HL)
	LD	B,A
	OUT	(BAUD0),A
	XOR	A
	LD	(HSTBUF+20H),A
	LD	(HSTBUF+21H),BC ; SAVE FOR INIT.SECTOR
CONF33: LD	HL,TXI6
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	AND	01011111B
	CP	'N'
	JR	Z,CONF35
	CP	'J'
	JR	NZ,CONF33
CONF34: LD	HL,TXI7
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	AND	01011111B
	CP	'L'
	JR	Z,CONF35
	CP	'U'
	JR	NZ,CONF34
CONF35: PUSH	AF
	LD	C,27
	CALL	CONOUT
	LD	C,'b'
	CALL	CONOUT
	POP	AF
	LD	(HSTBUF+6),A	; I, U OR L
	LD	C,A
	CALL	CONOUT
CONF36: LD	HL,TXI8
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	AND	01011111B
	CP	'S'
	JR	Z,CONF37
	CP	'O'
	JR	NZ,CONF36
CONF37: PUSH	AF
	LD	C,27
	CALL	CONOUT
	LD	C,'b'
	CALL	CONOUT
	POP	AF
	LD	(HSTBUF+7),A	; S OR O
	LD	C,A
	CALL	CONOUT
CON37:	LD	HL,TXI9
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	CP	'0'
	JR	Z,CONF38
	CP	'1'
	JR	NZ,CON37
CONF38: PUSH	AF
	LD	C,27
	CALL	CONOUT
	LD	C,'b'
	CALL	CONOUT
	POP	AF
	LD	(HSTBUF+8),A	; 0 OR 1
	LD	C,A
	CALL	CONOUT
	JP	CONF01
CONF39: LD	HL,TX5
	CALL	OUTTX
	JP	CONF31
TX4:	DEFB	27,'*'
	DEFB	0DH,0AH
	DEFM	'Der kan vælges mellem følgende'
	DEFB	0DH,0AH
	DEFM	'baudrate for seriekanalen:'
	DEFB	0DH,0AH,0AH
	DEFM	'2. 19.200 BAUD'
	DEFB	0DH,0AH
	DEFM	'3.  9.600 "'
	DEFB	0DH,0AH
	DEFM	'4.  4.800 "'
	DEFB	0DH,0AH
	DEFM	'5.  2.400 "'
	DEFB	0DH,0AH
	DEFM	'6.  1.200 "'
	DEFB	0DH,0AH
	DEFM	'7.    600 "'
	DEFB	0DH,0AH
	DEFM	'8.    300 "'
	DEFB	0DH,0AH
	DEFM	'9.    110 "'
TX5:	DEFB	0DH,0AH,0AH
	DEFM	'Hvilken ( 2 - 9 ) ønskes ? '
	DEFB	0
TXI6:	DEFB	27,'*',0AH,0AH
	DEFM	'Skal der være paritet (J/N) ? '
	DEFB	0
TXI7:	DEFB	0DH,0AH,0AH
	DEFM	'Lige eller ulige (L/U) ? '
	DEFB	0
TXI8:	DEFB	0DH,0AH,0AH
	DEFM	'Skal der være 7 eller 8 databit (S/O) ? '
	DEFB	0
TXI9:	DEFB	0DH,0AH,0AH
	DEFM	'Skal "BUSY" linien være aktiv høj eller lav (1/0) ? '
	DEFB	0

CONF40: LD	HL,TX9		; SET SCREEN
	CALL	OUTTX
	CALL	CONIN
	PUSH	AF
	LD	C,A
	CALL	CONOUT
	POP	AF
	CP	34H
	JR	NZ,CONF42
	LD	A,40
	LD	(HSTBUF+1),A
	JP	CONF01
CONF42: CP	38H
	JR	NZ,CONF40
	LD	A,80
	LD	(HSTBUF+1),A
	JP	CONF01
TX9:	DEFB	27,'*'
	DEFB	0DH,0AH
	DEFM	'Skal skærmen arbejde med 40'
	DEFB	0DH,0AH
	DEFM	'eller 80 tegn i bredden ? '
	DEFB	0DH,0AH
	DEFM	'Angiv 4 eller 8: '
	DEFB	0

;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; PROCEDURE DELAY
;
;  PARAMETRE IND: A = ANTAL PERIODER A 5 MS, DER SKAL
;  VENTES
;  PARAMETRE UD : INGEN
;
; BRUGER AF
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

DELAY:	PUSH	DE		; STAK DE
DELAY1: LD	E,30		; REPEAT E := 30
DELAY2: LD	D,22		;   REPEAT D := 22
DELAY3: DEC	D		;     REPEAT D := D-1
	JR	NZ,DELAY3	;	UNTIL D := 0
				;     (NU ER DER GAAET
				;      166,5 MS)
	DEC	E		;     E := E-1
	JR	NZ,DELAY2	;  UNTIL E = 0
				;   (NU ER DER GAAET 5 MS)
	DEC	A
	JR	NZ,DELAY1
	POP	DE
	RET

MSGC:
	DEFB	0DH,0AH
	DEFM	'BUTLER operativsystem v. '
SNR:	DEFM	'1.30'
	DEFB	0DH,0AH,0AH
	DEFM	'Indsæt en CP/M systemdisk i det øverste'
	DEFB	0DH,0AH
	DEFM	'diskdrev og tryk på "RETURN"'
	DEFB	0
MSGC1:	DEFB	27,'*',0AH,0AH
	DEFM	'Konfigurerings mode'
	DEFB	0DH,0AH,0AH
	DEFM	'* 1. Diskformater'
	DEFB	0DH,0AH
	DEFM	'  2. Indstilling af ur'
	DEFB	0DH,0AH
	DEFM	'* 3. Indstilling af seriekanal'
	DEFB	0DH,0AH
	DEFM	'* 4. Antal tegn på skærmen'
	DEFB	0DH,0AH
	DEFM	'* 5. Streng til funktionstaster'
	DEFB	0DH,0AH
	DEFM	'* 6. Autostart'
	DEFB	0DH,0AH
	DEFM	'* 7. Tastaturbuffer'
	DEFB	0DH,0AH
	DEFM	'* 8. Valg af printer'
	DEFB	0DH,0AH
	DEFM	'* 9. Slet initialiseringssektor'
	DEFB	0DH,0AH,0AH
	DEFM	'Tryk "RETURN" for normal opstart'
	DEFB	0DH,0AH,0AH
	DEFM	'Hvilken funktion skal udføres? '
	DEFB	0
MSGC2:	DEFB	0DH,0AH,0AH
	DEFM	'Skal de med "*" mærkede muligheder'
	DEFB	0DH,0AH
	DEFM	'udskrives på disken (J/N) ? '
	DEFB	0
MSGC3:	DEFM	' K CP/M system'
	DEFB	0DH,0AH,0AH,00
TEXT3:	DEFB	27,'*',0AH
	DEFM	'Der kan vælges mellem følgende formater:'
	DEFB	0DH,0AH,0AH
	DEFM	'1. Dobbeltsidet 80 spor'
	DEFB	0DH,0AH,0AH
	DEFM	'2. Enkeltsidet 40 spor'
	DEFB	0DH,0AH,0AH
	DEFM	'3. Dobbeltsidet 40 spor'
	DEFB	0DH,0AH,0AH
	DEFM	'Hvilket format ( 1 - 3 ) ? '
	DEFB	0
TEXT4:	DEFB	0DH,0AH,0AH
	DEFM	'Hvilket diskdrev ( 0 - 3 ) ? '
	DEFB	0
TEXT5:	DEFB	0DH,0AH,0AH
	DEFM	'Flere (J/-) ? '
	DEFB	0
TEXT6:	DEFB	0AH
	DEFM	'Drev 0 (A:) indeholder ikke en CP/M systemdisk!'
	DEFB	0DH,0AH,0
;	EJECT
	TITLE	JUMP VECTOR AND TABLES
;
; THE JUMP VECTOR WHICH ESTABLISHES THE CONNECTION
; BETWEEN BDOS AND CBIOS
;
JTAB:	JP	BOOT		; COLD START
WBOOTE: JP	WBOOT		; WARM START
	JP	CONST		; RETURN CONSOLE STATUS
	JP	CONIN		; CONSOLE CHARACTER IN
	JP	CONOUT		; CONSOLE CHARACTER OUT
	JP	LIST		; LIST CHARACTER OUT
	JP	PUNCH		; PUNCH CHARACTER OUT
	JP	READER		; READER CHARACTER IN
	JP	HOME		; MOVE DISK HEAD TO HOME
				;   POSITION
	JP	SELDSK		; SELECT DISK
	JP	SETTRK		; SET TRACK NO
	JP	SETSEC		; SET SECTOR NO
	JP	SETDMA		; SET DMA ADDRESS
	JP	READ		; READ DISK
	JP	WRITE		; WRITE DISK
	JP	LISTST		; RETURN LIST STATUS
	JP	SECTRAN 	; SECTOR TRANSLATE
JVEC0:


;
; SECTOR TRANSLATE VECTOR
;
TR1:
TR0:	DEFB	1,04,07,0AH	; SECTORS 1-4
	DEFB	03,06,09,02	; SECTORS 5-8
	DEFB	05,08		; SECTORS 9-10
RCSYFO:
TR2:	DEFB	1,3,5,7
	DEFB	9,2,4,6
	DEFB	8

;	EJECT
;	TITLE	BOOT, WBOOT
;
; BOOT - COLD START AFTER SYSTEM LOAD
;
BOOT:				; SIMPLEST CASE IS TO JUST
				; PERFORM PARAMETER
	LD	SP,DIRBF+50
	LD	HL,SPECIO+OFFSET
	CALL	COMMAND 	; COMMAND(SPECIFY)
	LD	A,01
	OUT	(RAMBAW),A	; OPEN RAM FOR WRITE
	LD	(RAMWR),A
	XOR	A
	LD	(CDISK),A
	LD	(HSTACT),A	; HOST BUFFER INACTIVE
	LD	(UNACNT),A	; CLEAR UNALLOC COUNT
	LD	HL,000H
	CALL	OUTRFRSH	; OUTRFRSH(0)
;	 CALL	 OUTCUR
	JP	GOCPMW		; INIT AND GO TO CP/M


;
; WBOOT - WARM START, THAT IS, RELOAD THE CCP AND BDOS
;

WBOOT:				; SIMPLEST CASE IS TO READ
				;   THE DISK UNTIL ALL
				;   SECTORS HAVE BEEN READ
	LD	SP,DIRBF+50	; SET UP STACK - CP/M IS
				;   NOT RUNNING, SO DIRBUF
				;   IS FREE
	XOR	A
	LD	(HSTACT),A
	LD	(UNACNT),A
	LD	HL,SPECIO+OFFSET
	CALL	COMMAND 	; COMMAND(SPECIFY)
	LD	C,0		; SELECT DISK 0
	CALL	SELDSK
	CALL	HOME
;
; NOW, READ IN THE CP/M SYSTEM. IT STARTS AT TRACK 00,
; SECTOR 2 (SECTOR 1 CONTAINS THE COLD START LOADER).
; THE LENGTH IS 'NSECTS' BLOCKS.
;
; WHEN THE READ-IN STARTS, DISK 0 IS SELECTED AND
; RECALIBRATED (SET TO TRACK 0)
;
	DI
	LD	A,1		; OPEN RAM FOR WRITE
	OUT	(RAMBAW),A
	LD	(RAMWR),A
	CALL	MOTORS
	CALL	STAR12
	LD	A,10
	LD	(RDEOT+OFFSET),A
	LD	BC,(CCPSTO)
	DI
	CALL	RTRACK
	EI
	OR	A
	JR	NZ,WBOO10	; NOT METANIC OR HH
	LD	DE,HSTBUF	; CHECK FORMAT ROUTINE
	LD	HL,STAR30
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,(CCPSTO)	;
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	CP	0C3H		; METANIC FORMAT?
	JP	Z,WBOO20	; YES
	LD	DE,512
	ADD	HL,DE
	CALL	HSTBUF		; (STAR30)
	LD	A,B
	CP	0C3H		; HH FORMAT
	JP	Z,WBOO30
	LD	HL,TEXT6
	CALL	OUTTX
	JP	START1
WBOO10:
	XOR	A
	LD	(HSTDSK),A
	LD	(SEEKNO+OFFSET),A
	LD	(HEADNO+OFFSET),A
	INC	A
	LD	(HSTTRK),A
	INC	A
	LD	(SEEKTR+OFFSET),A
	LD	(DISKFO+OFFSET),A
	LD	A,09H		; NO OF LAST SECTOR
	LD	(IOEOT+OFFSET),A
	LD	A,46H
	LD	(IOCMD+OFFSET),A
	LD	B,0BH		; NO OF SECTORS
	LD	C,0		; SECTOR COUNTER
	LD	DE,(CCPSTO)
WBOO15: PUSH	BC
	PUSH	DE
	LD	HL,RCSYFO
	LD	B,0
	ADD	HL,BC
	LD	A,(HL)
	LD	(SECTOR),A
	CALL	IOSEC
	OR	A
	POP	DE
	POP	BC
	JR	NZ,WBOO15
	PUSH	BC
	LD	HL,HSTBUF
	LD	BC,512
	LDIR
	POP	BC
	DEC	B
	JR	Z,RCFUS
	INC	C
	LD	A,C
	CP	09H
	JR	C,WBOO15
	LD	C,0
	LD	A,1
	LD	(HEADNO+OFFSET),A
	JP	WBOO15
RCFUS:	LD	HL,STAR30
	LD	DE,HSTBUF
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,(CCPSTO)
	CALL	TESTSY
	JP	GOCPMW
WBOO20:
	CALL	TESTSY			; METANIC FORMAT
WBOO21: XOR	A
	LD	(HSTDSK),A
	LD	(SEEKTR+OFFSET),A
	LD	(SEEKNO+OFFSET),A
	LD	(DISKFO+OFFSET),A
	INC	A
	LD	(HSTTRK),A
	LD	(SECTOR),A
	LD	(HEADNO+OFFSET),A
	LD	A,46H
	LD	(IOCMD+OFFSET),A
	CALL	IOSEC
	LD	HL,(CCPSTO)
	LD	DE,10*512
	ADD	HL,DE
	EX	DE,HL
	LD	HL,HSTBUF
	LD	BC,512
	LDIR
	JP	GOCPMW
WBOO30: CALL	TESTSY
	LD	A,1
	LD	(DISKFO+OFFSET),A
	PUSH	HL
	LD	HL,STAR40
	LD	DE,HSTBUF
	LD	BC,STAR50-STAR40
	LDIR
	POP	HL
	LD	DE,(CCPSTO)	; MOVE CP/M IN PLACE
	LD	BC,512*9
	CALL	HSTBUF
	PUSH	DE
	XOR	A
	LD	(HSTDSK),A
	LD	(HEADNO+OFFSET),A
	LD	(SEEKNO+OFFSET),A
	INC	A
	LD	(SECTOR),A
	LD	(HSTTRK),A
	INC	A
	LD	(SEEKTR+OFFSET),A
	LD	A,10
	LD	(IOEOT+OFFSET),A
	LD	A,46H
	LD	(IOCMD+OFFSET),A
	CALL	IOSEC
	POP	DE
	LD	HL,HSTBUF
	LD	BC,512
	LDIR
	PUSH	DE
	LD	A,2
	LD	(SECTOR),A
	CALL	IOSEC
	POP	DE
	LD	HL,HSTBUF
	LD	BC,512
	LDIR
	JP	GOCPMW

TESTSY: INC	HL
	INC	HL
	CALL	HSTBUF
	LD	A,B
	SUB	3
	LD	HL,CCPSTO+1
	CP	(HL)
	RET	Z
	LD	HL,TXTSY
	CALL	OUTTX
TESY10: CALL	CONIN
	CP	0DH
	JR	NZ,TESY10
	LD	C,0DH
	CALL	CONOUT
	LD	C,0AH
	CALL	CONOUT
	JP	WBOOT

TXTSY:	DEFB	0DH,0AH,0AH,27,'I'
	DEFM	'CP/M systemet har forkert størrelse!'
	DEFB	0DH,0AH,0AH
	DEFB	27,'i'
	DEFM	'Indsæt ny disk og tryk på RETURN '
	DEFB	0
;
; THE WHOLE CP/M SYSTEM HAS BEEN LOADED. NOW, SET UP
; THE PARAMETERS THAT CP/M REQUIRES AND JUMP TO CCP
;
; THIS ENTRY POINT IS USED BY THE COLD START, TOO.
;
GOCPMC: CALL	GOCPM
	CALL	GOCPM1
	JP	GOCPM2
GOCPMW: CALL	GOCPM
	JP	GOCPM2
GOCPM:
	LD	A,01		; OPEN RAM FOR WRITE
	OUT	(RAMBAW),A
	LD	(RAMWR),A
	LD	B,11H
	LD	HL,(CCPSTORE)
	LD	DE,1600H
	ADD	HL,DE
	LD	A,0CDH
	LD	DE,XJTAB+OFFSET
GOCP10: LD	(HL),A
	INC	HL
	LD	(HL),E
	INC	HL
	LD	(HL),D
	INC	HL
	DJNZ	GOCP10
	LD	A,0C3H		; (0H..2H) := JP GOTOCCP
	LD	(0),A
	LD	DE,1603H
	LD	HL,(CCPSTO)
	ADD	HL,DE
	LD	(1),HL
	LD	HL,(CCPSTO)
	LD	DE,806H
	ADD	HL,DE
	LD	(5),A		; (5H..7H) := JP BDOS
	LD	(6),HL
	LD	BC,80H		; SET_DMA(80H)
	CALL	SETDMA		;   (* DEFAULT VALUE *)
	RET

GOCPM1:
	LD	HL,STAR30
	LD	DE,HSTBUF
	LD	BC,STAR40-STAR30
	LDIR
	LD	HL,100H+512*13
	CALL	HSTBUF
	LD	A,B
	OR	A
	CALL	Z,INIT1
	RET

GOCPM2:
	LD	HL,GOCP30
	LD	DE,HSTBUF
	LD	BC,GOCP40-GOCP30
	LDIR
	JP	HSTBUF
INIT1:	PUSH	HL
	LD	HL,GOCP80
	LD	DE,HSTBUF
	LD	BC,GOCP90-GOCP80
	LDIR
	POP	HL
	JP	HSTBUF
GOCP80: DI
	LD	A,1
	OUT	(RAMBAR),A
	LD	(RAMRD),A
	LD	A,80H
	OUT	(SYSBAN),A
	LD	(SYBAN),A
	JP	(HL)
GOCP90:
GOCP30: DI
	LD	A,1
	OUT	(RAMBAR),A
	LD	(RAMRD),A
	LD	A,80H
	OUT	(SYSBAN),A
	LD	(SYBAN),A
	LD	A,(CDISK)
	LD	C,A
	LD	HL,(CCPSTORE)
	EI
	JP	(HL)
GOCP40:
;	EJECT
;	TITLE SELDSK

;
; SELECT A DISK FOR SUBSEQUENT TRANSFERS
; THE DISK NUMBER IS INPUT IN C (0...)
; THE ADDRESS OF THE DISK PARAMETER BLOCK FOR THE DISK
; IS RETURNED IN HL; 0 IS RETURNED IF THE DISK DOES
; NOT EXIST.
;

SELDSK:
	PUSH	BC
	CALL	MOTORS
	POP	BC
	LD	A,C
	CP	04
	JR	C,SELD2
SELD1:
	LD	HL,0
	RET
SELD2:
	LD	A,C
	LD	(RECANO+OFFSET),A
	LD	(SEKDSK),A
	LD	BC,DPBAS1-DPBAS0
	LD	HL,DPBAS0+OFFSET
	OR	A
SELD4:	RET	Z
	ADD	HL,BC
	DEC	A
	JR	SELD4

;


CONST:
	LD	A,(KBFLAG)
	OR	A
	RET

;
; READ A CHARACTER FROM THE KEYBOARD
;   RETURN A = CHARACTER WITH THE PARITY BIT RESET
;

CONIN:
	LD	A,(KBFLAG)
	OR	A
	JR	Z,CONIN
	DI
	LD	A,(KBFLAG)
	DEC	A
	LD	(KBFLAG),A
	LD	C,A
	LD	B,0
	LD	A,(KBBUF)
	JR	Z,CONIAB
	LD	HL,KBBUF+1
	LD	DE,KBBUF
	LDIR
CONIAB: AND	7FH
	EI
	RET
CONI05:

CONI21:
	LD	A,(KEYSAVE)
	LD	C,A
	LD	DE,(KEYSAVE+1)
	LD	A,C		; GET COLUMN
	OR	11000001B
	CALL	TESTLI		; TEST FOR 1 LINE
	JP	NZ,FAKE 	; TWO OR MORE DOWN
	LD	A,C
	AND	00000001B
	JR	NZ,CONI22
	LD	HL,ASCTAB	; CHARACTER TABLE
	JR	CONI25
CONI22: LD	HL,ASCTA1
CONI25: LD	B,05
	LD	A,C
	RRA			; MOVE INTO POSITION
CONI30: RRA
	JR	NC,CONI40
	PUSH	BC
	LD	BC,16
	ADD	HL,BC		; UPDATE HL
	POP	BC
	DJNZ	CONI30
	JR	FAKE		; NO LINE DOWN
CONI40:
	LD	A,E
	CALL	TESTLI
	JR	NZ,FAKE
	LD	A,D
	CALL	TESTLI
	JR	NZ,FAKE 	; MORE THAN 1 LINE
	LD	A,E
	CP	0FFH
	JR	Z,CONI45
	LD	A,D
	CP	0FFH
	JR	NZ,FAKE
CONI45: LD	A,D
	LD	B,8
CONI50: RLA
	JR	NC,CONI70
	INC	HL
	DJNZ	CONI50
	LD	A,E
	LD	B,8
CONI60: RLA
	JR	NC,CONI70
	INC	HL
	DJNZ	CONI60
	JR	FAKE
CONI70:
	LD	A,(HL)		; GET CHARACTER
	CP	80H
	JR	NC,FUNCTA
	LD	B,A		; SAVE IN B
	LD	A,C		; GET COLUMN
	RLA			; MOVE LEFT
	JR	C,CONI90	; CONTROL DOWN ?
	LD	A,B
	AND	00011111B
	LD	B,A
	JR	CONI95
CONI90: LD	A,C
	RLA
	RLA
	JR	C,CONI95
	LD	A,B
	CP	41H		; TEST FOR ALPHA LOCK
	JR	C,CONI95
	CP	7EH
	JR	NC,CONI95
	RES	5,B
CONI95:
	LD	A,(TASTBU)
	OR	A
	JR	Z,CONI97
	LD	A,(KBFLAG)
	CP	80
	RET	Z
	LD	HL,KBBUF
	LD	E,A
	LD	D,0
	ADD	HL,DE
	LD	A,B
	LD	(HL),A
	LD	A,E
	INC	A
	LD	(KBFLAG),A
FAKE:
	RET
CONI97: LD	A,B
	LD	(KBBUF),A
	LD	A,1
	LD	(KBFLAG),A
	RET

TESTLI: CPL
	LD	B,A
	NEG
	AND	B
	SUB	B
	RET
FUNCTA: CP	90H
	JR	C,FUNC10
	JR	NZ,FUNC20
	LD	A,(OLINE)
	CPL
	LD	(OLINE),A
	RET
FUNC10: AND	00000111B	; REMOVE BIT 4-7
	LD	B,A		; STORE IN B
	LD	A,C
	RLA
	JR	C,FUNC15
	SET	3,B
FUNC15:
	LD	HL,FBUF-1
	LD	A,B
	OR	A
	JR	Z,FUNC18
FUNC17:
	INC	HL
	LD	A,(HL)
	CP	80H
	JR	C,FUNC17
	DEC	B
	JR	NZ,FUNC17
FUNC18: INC	HL
	LD	A,(HL)
	CP	80H
	RET	Z		; ZERO STRING
	LD	B,A
	LD	A,(KBFLAG)
	CP	80
	RET	Z
	PUSH	HL
	LD	E,A
	LD	D,0
	LD	HL,KBBUF
	ADD	HL,DE
	LD	A,B
	LD	(HL),A
	LD	A,E
	INC	A
	LD	(KBFLAG),A
	POP	HL
	LD	A,B
	CP	80H
	RET	NC
	JR	FUNC18
FUNC20: CP	91H
	JR	NZ,FUNC30
	LD	A,(ULINE)
	CPL
	LD	(ULINE),A
	RET
FUNC30: CP	92H
	JR	NZ,FUNC40
	LD	A,(INVERT)
	CPL
	LD	(INVERT),A
	RET
FUNC40: CP	98H
	JR	NZ,FUNC50
	LD	C,27
	CALL	CONOUT
	LD	C,'H'
	CALL	CONOUT
	LD	A,(MODE)
	LD	C,A
	CALL	CONOUT
	RET

FUNC50: RET

;
; OUTPUT A CHARACTER TO THE LIST DEVICE
; THE CHARACTER IS INPUT IN C
;

LIST:	CALL	LISTST
	OR	A
	JR	Z,LIST
	LD	A,C
	OUT	(LPDP),A
	IN	A,(LPSP)
	RES	STROBE,A
	OUT	(LPSP),A
	SET	STROBE,A
	OUT	(LPSP),A
	LD	A,C
	RET
;
;
; RETURN LIST STATUS IN A (0 - NOT READY; 0FFH - READY)
;

LISTST: IN	A,(LPSP)
	AND	EMPTY+BUSY
	LD	A,0FFH
	RET	Z
	INC	A
	RET
;
;
; PUNCH A CHARACTER INPUT IN REGISTER C
;

PUNCH:
	LD	A,(BUSYLI)
	AND	00100000B
	LD	B,A
PUNC10:
	LD	A,00010000B
	OUT	(DARTAC),A
	IN	A,(DARTAC)
	AND	00100000B
	CP	B
	JR	NZ,PUNC10
PUNC20:
	IN	A,(DARTAC)
	AND	00000100B
	JR	Z,PUNC20
	LD	A,C
	OUT	(DARTAD),A
	RET


;
; READ A CHARACTER FROM THE READER TO REGISTER A  WITH
; THE PARITY BIT RESET. CTRL-Z INDICATES EOF.
;

READER:
	LD	A,(BUSYLI)
	AND	00001000B
	LD	B,A
READE2:
	LD	A,00010000B
	OUT	(DARTAC),A
	IN	A,(DARTAC)
	AND	00001000B
	CP	B
	JR	NZ,READE2
READE3: IN	A,(DARTAC)
	AND	00000001B
	JR	Z,READE3
	IN	A,(DARTAD)
	AND	7FH
	RET


;	 EJECT
;	 TITLE	 DISK HANDLER
;
; DISK HANDLER
;
;
; RECALIBRATE THE CURRENT DISK
;
HOME:
	CALL	MOTORS
	LD	HL,RECALIBRATE+OFFSET  ; COMMAND(RECALIBRATE)
	CALL	COMMAND
	CALL	ENDSEEK
	LD	HL,RECALIBRATE+OFFSET
	CALL	COMMAND
	CALL	ENDSEEK
	RET

;
; SELECT A TRACK FOR SUBSEQUENT TRANSFERS
; THE TRACK NUMBER IS INPUT IN BC (0...)
;

SETTRK:
	LD	H,B
	LD	L,C
	LD	(SEKTR),HL
	RET

;
; SELECT A SECTOR FOR SUBSEQUENT TRANSFERS.
; THE SECTOR NUMBER IS INPUT IN BC (RANGE AS THE RETURN
; VALUE FROM SECTRAN).
;

SETSEC:
	LD	A,C
	LD	(SEKSEC),A
	RET
;
; TRANSLATE A LOGICAL SECTOR NUMBER TO A PHYSICAL
; SECTOR NUMBER. THE LOGICAL SECTOR NUMBER (0...) IS
; INPUT IN BC AND DE POINTS OUT THE TRANSLATE TABLE TO
; BE USED.
; THE RESULTANT PHYSICAL SECTOR NUMBER IS RETURNED IN HL.
;

SECTRAN:
	LD	H,B
	LD	L,C
	RET

;
; SET THE DMA ADDRESS FOR SUBSEQUENT TRANSFERS.
; THE DMA ADDRESS IS INPUT IN BC.
;

SETDMA:
	LD	(DMAADR),BC   ; DMA_ADDRESS := BC
	RET

;
; READ OR WRITE A SECTOR ACCORDING TO THE PREVIOUSLY GIVEN
; SPECIFICATIONS (DISK, TRACK, SECTOR, DMA ADDRESS).
; RETURN A = 0 IF SUCCES, = 1 IF FAILURE.
;


;	 EJECT
;	 TITLE	 READ/WRITE

READ:	XOR	A
	LD	(UNACNT),A
	LD	A,1
	LD	(READOP),A	; READ OPERATION
	LD	(RSFLAG),A	; MUST READ DATA
	LD	A,WRUAL
	LD	(WRTYPE),A	; TREAT AS UNALLOC
	JP	RWOPER

WRITE:	XOR	A		; 0 TO ACCUMULATOR
	LD	(READOP),A	; NOT A READ OPERATION
	LD	A,C		; WRITE TYPE IN C
	LD	(WRTYPE),A
	CP	WRUAL		; WRITE UNALLOCATED?
	JP	NZ,CHKUNA	; CHECK FOR UNALLOC
;
; WRITE TO UNALLOCATED, SET PARAMETERS
;
	LD	A,BLKSIZ/128	; NEXT UNALLOC RECS
	LD	(UNACNT),A
	LD	A,(SEKDSK)	; DISK TO SEEK
	LD	(UNADSK),A	; UNADSK = SEKDSK
	LD	HL,(SEKTR)	;
	LD	(UNATRK),HL
	LD	A,(SEKSEC)
	LD	(UNASEC),A	; UNASEC = SEKSEC
;
; CHECK FOR WRITE TO UNALLOCATED SECTOR
;
CHKUNA:  LD	 A,(UNACNT)	 ; ANY UNALLOC REMAIN
	OR	A
	JP	Z,ALLOC 	; SKIP IF NOT
;
; MORE UNALLOCATED RECORDS REMAIN
;
	DEC	A		; UNACNT = UNACNT-1
	LD	(UNACNT),A
	LD	A,(SEKDSK)	; SAME DISK?
	LD	HL,UNADSK
	CP	(HL)		; SEKDSK = UNADSK
	JP	NZ,ALLOC	; SKIP IF NOT
;
; DISKS ARE THE SAME
;
	LD	HL,UNATRK
	CALL	SEKTRKCMP	; SEKTRK = UNATRK
	JP	NZ,ALLOC
;
; TRACKS ARE THE SAME
;
	LD	A,(SEKSEC)	; SAME SECTOR
	LD	HL,UNASEC
	CP	(HL)		; SEKSEC = UNASEC
	JP	NZ,ALLOC	; SKIP IF NOT
;
; MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF
;
	INC	(HL)		; UNASEC = UNASEC+1
	LD	A,(HL)		; END OF TRACK?
	CP	CPMSPT		; COUNT CP/M SECTORS
	JP	C,NOOVF 	; SKIP IF NO OVERFLOW
;
; OVERFLOW TO NEXT TRACK
;
	LD	(HL),0		; UNASEC = 0
	LD	HL,(UNATRK)
	INC	HL
	LD	(UNATRK),HL	; UNATRK = UNATRK+1
;
; MATCH FOUND, MARK AS UNNECESSARY READ
;
NOOVF:	 XOR	 A		 ; 0 TO ACCUMULATOR
	LD	(RSFLAG),A	; RSFLAG = 0
	JP	RWOPER		; TO PERFORM THE WRITE
;
; NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
;
ALLOC:	 XOR	 A		 ; 0 TO ACCUM
	LD	(UNACNT),A	; UNACNT = 0
	INC	A		; 1 TO ACCUM
	LD	(RSFLAG),A	; RSFLAG = 1
;
; ENTER HERE TO PERFORM THE READ/WRITE
;
RWOPER: XOR	A		; ZERO TO ACCUM
	LD	(ERFLAG),A	; NO ERRORS (YET)
	LD	A,(SEKSEC)	; COMPUTE HOST SECTOR
	OR	A
	RRA
	OR	A
	RRA
	LD	(SEKHST),A	; HOST SECTOR TO SEEK
;
; ACTIVE HOST SECTOR
;
	LD	HL,HSTACT	; HOST ACTIVE FLAG
	LD	A,(HL)
	LD	(HL),1		; ALWAYS BECOMES 1
	OR	A		; WAS IT ALREADY?
	JP	Z,FILHST
;
; HOST BUFFER ACTIVE, SAME AS SEEK BUFFER
;
	LD	A,(SEKDSK)
	LD	HL,HSTDSK	; SAME DISK?
	CP	(HL)		; SEKDSK = HSTDSK
	JP	NZ,NOMATCH
;
; SAME DISK, SAME TRACK?
;
	LD	HL,HSTTRK
	CALL	SEKTRKCMP	; SEKTRK = HSTTRK?
	JP	NZ,NOMATCH
;
; SAME DISK, SAME TRACK, SAME BUFFER?
;


	LD	A,(SEKHST)
	LD	HL,HSTSEC	; SEKHST = HSTSEC
	CP	(HL)
	JP	Z,MATCH 	; SKIP IF MATCH
;
; PROPER DISK, BUT NOT CORRECT SECTOR
;
NOMATCH: LD	 A,(HSTWRT)	 ; HOST WRITTEN
	OR	A
	CALL	NZ,WRITEHST	; CLEAR HOST BUFFER
;
; MAY HAVE TO FILL THE HOST BUFFER
;
FILHST: LD	A,(SEKDSK)
	LD	(HSTDSK),A
	LD	HL,(SEKTR)
	LD	(HSTTRK),HL
	LD	A,(SEKHST)
	LD	(HSTSEC),A
	LD	A,(RSFLAG)	; NEED TO READ?
	OR	A
	CALL	NZ,READHST	; YES, IF 1
	XOR	A		; 0 TO ACCUM
	LD	(HSTWRT),A
;
; COPY DATA TO OR FROM BUFFER
;
MATCH:	LD	A,(SEKSEC)	; MASK BUFFER NUMBER
	AND	SECMSK		; LEAST SIGNIF BITS
	LD	L,A		; READY TO SHIFT
	LD	H,0		; DOUBLE COUNT
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
;
; HL HAS RELATIVE HOST BUFFER ADDRESS

	LD	DE,HSTBUF
	ADD	HL,DE		; HL = HOST ADDRESS
	EX	DE,HL		; NOW IN DE
	LD	HL,RWMO10
	PUSH	HL
	LD	HL,(DMAADR)	; GET/PUT CP/M DATA
	LD	C,128		; LENGTH OF MOVE
	LD	A,(READOP)	; WHICH WAY?
	OR	A
	JP	NZ,RWMOVE+OFFSET ; SKIP IF READ
;
; WRITE OPERATION, MARK AND SWITCH DIRECTION
;
	LD	A,1
	LD	(HSTWRT),A	; HSTWRT = 1
	EX	DE,HL		; SOURCE/DEST SWAP
	JP	RWMOVE+OFFSET
;
; C INITIALLY 128, DE IS SOURCE, HL IS DEST
;
;RWMOVE:
;	 LD	 A,(DE) 	 ; SOURCE CHARACTER
;	 INC	 DE
;	 LD	 (HL),A 	 ; TO DEST
;	 INC	 HL
;	 DEC	 C		 ; LOOP 128 TIMES
;	 JP	 NZ,RWMOVE
;
; DATA HAS BEEN MOVED TO/FROM HOST BUFFER
;
RWMO10: LD	A,(WRTYPE)	; WRITE TYPE
	CP	WRDIR		; TO DIRECTORY?
	LD	A,(ERFLAG)	; IN CASE OF ERRORS
	RET	NZ		; NO FURTHER PROCESSING
;
; CLEAR HOST BUFFER FOR DIRECTORY WRITE
;
	OR	A		; ERRORS
	RET	NZ		; SKIP IF SO
	XOR	A		; 0 TO ACCUM
	LD	(HSTWRT),A	; BUFFER WRITTEN
	CALL	WRITEHST
	LD	A,(ERFLAG)
	RET
;
; UTILITY SUBROUTINE FOR 16-BIT COMPARE
;
SEKTRKCMP:
	EX	DE,HL
	LD	HL,SEKTR
	LD	A,(DE)		; LOW BYTE COMPARE
	CP	(HL)		; SAME
	RET	NZ		; RETURN IF NOT
;
; LOW BYTES EQUAL, TEST HIGH IS
;
	INC	DE
	INC	HL
	LD	A,(DE)
	CP	(HL)		; SETS FLAGS
	RET
;

	INCLUDE BIOS2.ASM
	INCLUDE BIOS1.ASM
	INCLUDE BLOWUP.ASM
	INCLUDE BLOWU1.ASM
;	 INCLUDE CHARGE.ASM
	INCLUDE COMARE.ASM


«eof»