;SKELETAL CBIOS FOR FIRST LEVEL OF CP/M ALTERATION
;
;NOTE : MSIZE DETERMINES WHERE THIS CBIOS IS LOCATED
MSIZE        EQU       16        ;CP/M VERSION MEMORY SIZE IN KILOBYTES
PATCH        EQU       MSIZE*1024-2*256   ;START OF THE CBIOS PATCH
;
;WE WILL USE THE AREA RESERVED STARTING AT LOCATION
;40H IN PAGE 0 FOR HOLDING THE VALUES OF:
;            TRACK   =  LAST SELECTED TRACK
;            SECTOR  =  LAST SELECTED SECTOR
;            DMAAD   =  LAST SELECTED DMA ADDRESS
;            DISKNO  =  LAST SELECTED DISK NUMBER
;(NOTE THAT ALL ARE BYTE VALUES EXCEPT FOR DMAAD)
;
;
SCRAT        EQU       40H                ;BASE OF SCRATCH AREA (FROM 40H T
TRACK        EQU       SCRAT              ;CURRENTLY SELECTED TRACK
SECTOR       EQU       SCRAT+1            ;CURRERILY SELECTED SECTOR
DMAAD        EQU       SCRAT+2            ;CURRENT DMA ADDRESS
DISKNO       EQU       DMAAD+4   ;CURRENT DISK NUMBER
;
;
             ORG         PATCH     ;0RGIN OF THIS PROGRAM
CBASE        EQU       (MSIZE-16)*1024    ;BIAS FOR SYSTEMS LARGER THAN 16K
CPMB         EQU       CBASE+2900H        ;BASE OF CP/M (= BASE OF CCP)
BDOS         EQU       CBASE+3106H        ;BASE OF RESIDENT PORTION OF CP/M
CPML         EQU       $-CPMB             ;LENGTH OF THE CPM SYSTEM IN BYTES
NSECTS       EQU       CPML/128  ;NUMBER OF SECTORS TO LOAD ON WARM START
;
;JUMP  VECTOR FOR INDIVIDUAL SUBROUTINES
	JMP         BOOT                ;COLD START
WBOOTE:
	JMP         WBOOT               ;WARM START
	JMP         CONST               ;CONSOLE STATUS
	JMP         CONIN               ;CONSOLE CHARACTER IN
	JMP         CONOUT              ;CONSOLE CHARACTER OUT
	JMP         LIST                ;LIST CHARACTER OUT
	JMP         PUNCH               ;PUNCH CHARACTER OUT
	JMP         READER              ;READER CHARACTER OUT
	JMP         HOME                ;MOVE HEAD TO HOME POSITION
	JMP         SELDSK              ;SELECT DISK
	JMP         SETTRK              ;SET TRACK NUMBER
	JMP         SETSEC              ;SET SECTOR NUMBER
	JMP         SETDMA              ;SET DMA ADDRESS
	JMP         READ                ;READ DISK
	JMP         WRITE               ;WRITE DISK
;
;
;INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNCTION

BOOT:        ;SIMPLEST CASE IS TO JUST PERFORM PARAMETER INITIALIZATION
	JMP         GOCPM               ;INITIALIZE AND GO TO CP/M
;
	WBOOT:       ;SIMPLEST CASE IS TO READ THE DISK UNTIL ALL SECTORS LOADED
	LXI         SP,80H              ;USE SPACE BELOW BUFFER FOR STACK
	mvi         C,0                 ;SELECT DISK 0
	CALL        SELDSK
	CALL        HOME                ;GO TO TRACK 00
;
	MVI         B,NSECTS  ;B COUNTS THE NUMBER OF SECTORS TO LOAD
	MVI         C,0                 ;C HAS THE CURRENT TRACK NUMBER
	MVI         D,2                 ;D HAS THE NEXT SECTOR TO READ
;NOTE THAT  WE BEGIN BY READING TRACK 0, SECTOR 2 SINCE SECTOR 1
;CONTAINS THE COLD START LOADER, WHICH IS SKIPPED IN A WARM START
	LXI         H,CPMB              ;BASE OF CP/M (INITIAL LOAD POINT)

LOAD1:       ;LOAD ONE MORE SECTOR
	PUSH        B         ;SAVE SECTOR COUNT, CURRENT TRACK
	PUSH        D         ;SAVE NEXT SECTOR TO READ
	PUSH        H         ;SAVE DMA ADDRESS
	MOV         C,D       ;GET SECTOR ADDRESS TO REGISTER C
	CALL        SETSEC    ;SET SECTOR ADDRESS FROM REGISTER C
	POP         B         ;RECALL DMA ADDRESS TO B,C
	PUSH        B         ;REPLACE ON STACK FOR LATER RECALL
	CALL        SETDMA    ;SET DMA ADDRESS FROM B,C
;
;DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET
	CALL        READ
	CPI         00H       ;ANY ERRORS?
	JNZ         WBOOT     ;RETRY THE ENTIRE BOOT IF AN ERROR OCCURS
;
;NO ERROR, MOVE TO NEXT SECTOR
	POP         H         ;RECALL DMA ADDRESS
	LXI         D,128     ;DMA=DMA+128
	DAD         D         ;NEW DMA ADDRESS IS IN H,L
	POP         D         ;RECALL SECTOR ADDRESS
	POP         B         ;RECALL NUMBER OF SECTORS REMAINING, AND CURRENT TRK
	DCR         B         ;SECTORS=SECTORS-1
	JZ          GOCPM     ;TPANSFER TO CP/M IF ALL HAVE BEEN LOADED
;
;MORE SECTORS REMAIN  TO LOAD, CHECK FOR TRACK CHANGE
	INR         D
	MOV         A,D       ;SECTOR=27?, IF SO, CHANGE TRACKS
	CPI         27
	JC          LOAD1     ;CARRY GENERATED IF SECTOR<27
;
;END OF CURRENT TRACK, GO TO NEXT TRACK
	MVI         D,1       ;BEGIN WITH FIRST SECTOR OF NEXT TRACK
	INR         C         ;TRACK=TRACK+1
;
;SAVE REGISTER STATE, AND CHANGE TRACKS
	PUSH        B
 	PUSH        D
	PUSH        H
	CALL        SETTRK    ;TRACK ADDRESS SET FROM REGISTER C
	POP         H
	POP         D
	POP         B
	JMP         LOAD1     ;FOR ANOTHER SECTOR
;
;END OF LOAD OPERATION, SET PARAMETERS AND GO TO CP/M
                  GOCPM:
	MVI         A,0C3H    ;C3 IS A JMP INSTRUCTION
	STA         0         ;FOR JMP TO WBOOT
	LXI         H,WBOOTE  ;WBOOT ENTRY POINT
	SHLD        1         ;SET ADDRESS FIELD FOR JMP AT 0
;
	STA         5         ;FOR JMP TO BDOS
	LXI         H,BDOS    ;BDOS ENTRY POINT
	SHLD        6         ;ADDRESS FIELD OF JUMP AT 5 TO BDOS
;
	LXI         B,80H     ;DEFAULT DM ADDRESS IS 80H
	CALL        SETDMA
;
	EI                    ;ENABLE THE INTERRUPT SYSTEM
;FUTURE VERSIONS OF CCP WILL SELECT THE DISK GIVEN BY REGISTER
;C UPON ENTRY, HENCE ZERO IT IN THIS VERSION OF THE BIOS FOR
;FUTURE COMPATIBILITY.
	MVI         C,0       ;SELECT DISK ZERO AFTER INITIALIZATION
	JMP         CPMB      ;GO TO CP/M FOR FURTHER PROCESSING
;
;
;SIMPLE I/0 HANDLERS. (MUST BE FILLED IN BY USER)
;IN EACH CASE, THE ENTRY POINT IS PROVIDED, WITH SPACE RESERVED
;TO INSERT YOUR OWN CODE
;
CONST:       ;CONSOLE STATUS,RETURN 0FFH IF CHARACTER READY, 00H IF NOT
	DS          10H       ;SPACE FOR STATUS SUBROUTINE
	MVI         A,00H
	RET
;
CONIN:       ;CONSOLE CHARACTER INTO REGISTER A
	DS          10H       ;SPACE FOR INPUT ROUTINE
	ANI         7FH       ;STRIP PARITY BIT
	RET
;
                  CONOUT:      ;CONSOLE CHARACTER OUTPUT FROM REGISTER C
	MOV         A,C       ;GET TO ACCUMULATOR
	DS          10H       ;SPACE FOR OUTPUT ROUTINE
	RET
;
LIST:       ;LIST CHARACTER FROM REGISTER C
	MOV         A,C       ;CHARACTER TO REGISTER A
	RET                   ;NULL SUBROUTINE
;
PUNCH:       ;PUNCH CHARACTER FROM REGISTER C
	MOV         A,C       ;CHARACTER TO REGISTER A
	RET                   ;NULL SUBROUTINE
;
READER: 	;READ CHARACTER INTO REGISTER A FROM READER DEVICE
	MVI         A,1AH     ;ENTER END OF FILE FOR NOW (REPLACE LATER)
	ANI         7FH       ;REMEMBER TO STRIP PARITY BIT
	RET
;
;
; I/0 DRIVERS FOR THE DISK FOLLOW
; FOR NOW, WE WILL SIMPLY STORE THE PARAMETERS AWAY FOR USE
; IN THE READ AND WRITE SUBROUTINES
;
HOME:        ;MOVE TO THE TRACK 00 POSITION OF CUPRENT DRIVE
;TPANSLATE  THIS CALL INTO A SETTRK CALL WITH PARAMETER 00
	MVI         C,0       ;SELECT TRACK 0
	CALL        SETTRK
	RET         ;WE WILL MOVE TO 00 ON FIRST READ/WRITE
;
SELDSK:      ;SELECT DISK GIVEN BY REGISTER C
	MOV         A,C
	STA         DISKNO
	DS          10H       ;SPACE FOR DISK SELECTION ROUTINE
	RET
;
SETTRK:          ;SET TRACK GIVEN BY REGISTER C
	MOV         A,C
	STA         TRACK
	DS          10H       ;SPACE FOR TRACK SELECT
	RET
;
SETSEC:      ;SET SECTOR GIVEN BY REGISTER C
	MOV         A,C
	STA         SECTOR
	DS          10H       ;SPACE FOR SECTOR SELECT
	RET
;
SETDMA:      ;SET DMA ADDRESS GIVEN BY REGISTERS B AND C
	MOV         L,C       ;LOW ORDER ADDRESS
	MOV         H,B       ;HIGH ORDER ADDRESS
	SHLD        DMAAD     ;SAVE THE ADDRESS
	DS          10H       ;SPACE FOR SETTING THE DMA ADDRESS
	RET

READ:        ;PERFORM READ OPERATION (USUALLY THIS IS SIMILAR TO WRITE
;SO WE WILL ALLOW SPACE TO SET UP READ COMMAND, THEN USE
;COMMON CODE IN WRITE)
	DS          10H       ;SET UP READ COMMAND
	JMP         WAITIO    ;TO PERFORM THE ACTUAL I/0
                  ;
WRITE:       ;PERFORM A WRITE OPERATION
	DS          10H       ;SET UP WRITE COMMAND
;
WAITIO:      ;ENTER HERE FROM READ AND WRITE TO PERFORM THE ACTUAL I/0
;OPERATION. RETURN A 00H IN REGISTER A IF THE OPERATION COMPLETES
;PROPERLY, AND 01H IF AN ERROR OCCURS DURING THE READ OR WRITE
;
; IN THIS CASE, WE HAVE SAVED THE DISK NUMBER IN 'DISKNO' (0,1)
;                                THE TRACK NUMBER IN 'TRACK' (0-76)
;                                THE SECTOR NUMBER IN 'SECTOR' (1-26)
;                                THE DMA ADDRESS IN 'DMAAD' (0-65535)
;ALL REMAINING SPACE FROM $ THRU MSIZE*1024-1 IS AVAILABLE:
LEFT         EQU       (MSIZE*1024-1)-$     ;SPACE REMAINING IN CBIOS
;
	MVI         A,1       ;ERROR CONDITION
	RET                   ;REPLACED WHEN FILLED-IN
	END




