     1                  ;	SKELETAL CBIOS FOR FIRST LEVEL OF CP/M 2.0 ALTERATION
     2                  ;
     3   0014 =         MSIZE	EQU	20		;CP/M VERSION MEMORY SIZE IN KILOBYTES
     4                  ;
     5                  ;	"BIAS" IS ADDRESS OFFSET FROM 3400H FOR MEMORY SYSTEMS
     6                  ;	THAN 16K (REFERRED TO AS"B" THROUGHOUT THE TEXT)
     7                  ;
     8   0000 =         BIAS	EQU	(MSIZE-20)*1024
     9   3400 =         CCP	EQU	3400H+BIAS	;BASE OF CCP
    10   3C06 =         BDOS	EQU	CCP+806H	;BASE OF BDOS
    11   4A00 =         BIOS	EQU	CCP+1600H	;BASE OF BIOS
    12   0004 =         CDISK	EQU	0004H		;CURRENT DISK NUMBER 0=A,... L5=P
    13   0003 =         IOBYTE	EQU	0003H		;INTEL I/O BYTE
    14                  ;
    15   4A00           	ORG	BIOS		;ORIGIN OF THIS PROGRAM
    16   002C =         NSECTS	EQU	($-CCP)/128	;WARM START SECTOR COUNT
    17                  ;
    18                  ;	JUMP VECTOR FOR INDIVIDUAL SUBROUTINES
    19                  ;
    20   4A00 C39C4A    	JMP	BOOT	;COLD START
    21   4A03 C3A64A    WBOOTE:	JMP	WBOOT	;WARM START
    22   4A06 C3114B    	JMP	CONST	;CONSOLE STATUS
    23   4A09 C3244B    	JMP	CONIN	;CONSOLE CHARACTER IN
    24   4A0C C3374B    	JMP	CONOUT	;CONSOLE CHARACTER OUT
    25   4A0F C3494B    	JMP	LIST	;LIST CHARACTER OUT
    26   4A12 C34D4B    	JMP	PUNCH	;PUNCH CHARACTER OUT
    27   4A15 C34F4B    	JMP	READER	;READER CHARACTER OUT
    28   4A18 C3544B    	JMP	HOME	;MOVE HEAD TO HOME POSITION
    29   4A1B C35A4B    	JMP	SELDSK	;SELECT DISK
    30   4A1E C37D4B    	JMP	SETTRK	;SET TRACK NUMBER
    31   4A21 C3924B    	JMP	SETSEC	;SET SECTOR NUMBER
    32   4A24 C3AD4B    	JMP	SETDMA	;SET DMA ADDRESS
    33   4A27 C3C34B    	JMP	READ	;READ DISK
    34   4A2A C3D64B    	JMP	WRITE	;WRITE DISK
    35   4A2D C34B4B    	JMP	LISTST	;RETURN LIST STATUS
    36   4A30 C3A74B    	JMP	SECTRAN	;SECTOR TRANSLATE
    37                  ;
    38                  ;	FIXED DATA TABLES FOR FOUR-DRIVE STANDARD
    39                  ;	IBM-COMPATIBLE 8" DISKS
    40                  ;
    41                  ;	DISK PARAMETER HEADER FOR DISK 00
    42   4A33 734A0000  DPBASE:	DW	TRANS, 0000H
    43   4A37 00000000  	DW	0000H, 0000H
    44   4A3B F04C8D4A  	DW	DIRBF, DPBLK
    45   4A3F EC4D704D  	DW	CHK00, ALL00
    46                  ;	DISK PARAMETER HEADER FOR DISK 01
    47   4A43 734A0000  	DW	TRANS, 0000H
    48   4A47 00000000  	DW	0000H, 0000H
    49   4A4B F04C8D4A  	DW	DIRBF, DPBLK
    50   4A4F FC4D8F4D  	DW	CHK01, ALL01
    51                  ;	DISK PARAMETER HEADER FOR DISK 02
    52   4A53 734A0000  	DW	TRANS, 0000H
    53   4A57 00000000  	DW	0000H, 0000H
    54   4A5B F04C8D4A  	DW	DIRBF, DPBLK
    55   4A5F 0C4EAE4D  	DW	CHK02, ALL02
    56                  ;	DISK PARAMETER HEADER FOR DISK 03
    57   4A63 734A0000  	DW	TRANS, 0000H
    58   4A67 00000000  	DW	0000H, 0000H
    59   4A6B F04C8D4A  	DW	DIRBF, DPBLK
    60   4A6F 1C4ECD4D  	DW	CHK03, ALL03
    61                  ;
    62                  ;	SECTOR TRANSLATE VECTOR
    63   4A73 01070D13  TRANS:	DB	 1,  7, 13, 19	;SECTORS  1,  2,  3,  4
    64   4A77 19050B11  	DB	25,  5, 11, 17	;SECTORS  5,  6,  7,  6
    65   4A7B 1703090F  	DB	23,  3,  9, 15	;SECTORS  9, 10, 11, 12
    66   4A7F 1502080E  	DB	21,  2,  8, 14	;SECTORS 13, 14, 15, 16
    67   4A83 141A060C  	DB	20, 26,  6, 12	;SECTORS 17, 18, 19, 20
    68   4A87 1218040A  	DB	18, 24,  4, 10	;SECTORS 21, 22, 23, 24
    69   4A8B 1016      	DB	16, 22		;SECTORS 25, 26
    70                  ;
    71                  DPBLK:	;DISK PARAMETER BLOCK, COMMON TO ALL DISKS
    72   4A8D 1A00      	DW	26		;SECTORS PER TRACK
    73   4A8F 03        	DB	3		;BLOCK SHIFT FACTOR
    74   4A90 07        	DB	7		;BLOCK MASK
    75   4A91 00        	DB	0		;NULL MASK
    76   4A92 F200      	DW	242		;DISK SIZE-1
    77   4A94 3F00      	DW	63		;DIRECTORY MAX
    78   4A96 C0        	DB	192		;ALLOC 0
    79   4A97 00        	DB	0		;ALLOC 1
    80   4A98 1000      	DW	16		;CHECK SIZE
    81   4A9A 0200      	DW	2		;TRACK OFFSET
    82                  ;
    83                  ;	END OF FIXED TABLES
    84                  ;
    85                  ;	INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNCTION
    86                  BOOT:	;SIMPLEST CASE IS TO JUST PERFORM PARAMETER INITIALIZATION
    87   4A9C AF        	XRA	A		;ZERO IN THE ACCUM
    88   4A9D 320300    	STA	IOBYTE		;CLEAR THE IOBYTE
    89   4AA0 320400    	STA	CDISK		;SELECT DISK ZERO
    90   4AA3 C3EF4A    	JMP	GOCPM		;INITIALIZE AND GO TO CP/M
    91                  ;
    92                  WBOOT:	;SIMPLEST CASE IS TO READ THE DISK UNTIL ALL SECTORS LOADED
    93   4AA6 318000    	LXI	SP, 80H		;USE SPACE BELOW BUFFER FOR STACK
    94   4AA9 0E00      	MVI	C, 0		;SELECT DISK 0
    95   4AAB CD5A4B    	CALL	SELDSK
    96   4AAE CD544B    	CALL	HOME		;GO TO TRACK 00
    97                  ;
    98   4AB1 062C      	MVI	B, NSECTS	;B COUNTS * OF SECTORS TO LOAD
    99   4AB3 0E00      	MVI	C, 0		;C HAS THE CURRENT TRACK NUMBER
   100   4AB5 1602      	MVI	D, 2		;D HAS THE NEXT SECTOR TO READ
   101                  ;	NOTE THAT WE BEGIN BY READING TRACK 0, SECTOR 2 SINCE SECTOR 1
   102                  ;	CONTAINS THE COLD START LOADER, WHICH IS SKIPPED IN A WARM START
   103   4AB7 210034    	LXI	H, CCP		;BASE OF CP/M (INITIAL LOAD POINT)
   104                  LOAD1:	;LOAD	ONE MORE SECTOR
   105   4ABA C5        	PUSH	B		;SAVE SECTOR COUNT, CURRENT TRACK
   106   4ABB D5        	PUSH	D		;SAVE NEXT SECTOR TO READ
   107   4ABC E5        	PUSH	H		;SAVE DMA ADDRESS
   108   4ABD 4A        	MOV	C, D		;GET SECTOR ADDRESS TO REGISTER C
   109   4ABE CD924B    	CALL	SETSEC		;SET SECTOR ADDRESS FROM REGISTER C
   110   4AC1 C1        	POP	B		;RECALL DMA ADDRESS TO B, C
   111   4AC2 C5        	PUSH	B		;REPLACE ON STACK FOR LATER RECALL
   112   4AC3 CDAD4B    	CALL	SETDMA		;SET DMA ADDRESS FROM B, C
   113                  ;
   114                  ;	DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET
   115   4AC6 CDC34B    	CALL	READ
   116   4AC9 FE00      	CPI	00H		;ANY ERRORS?
   117   4ACB C2A64A    	JNZ	WBOOT		;RETRY THE ENTIRE BOOT IF AN ERROR OCCURS
   118                  ;
   119                  ;	NO ERROR, MOVE TO NEXT SECTOR
   120   4ACE E1        	POP	H		;RECALL DMA ADDRESS
   121   4ACF 118000    	LXI	D, 128		;DMA=DMA+128
   122   4AD2 19        	DAD	D		;NEW DMA ADDRESS IS IN H, L
   123   4AD3 D1        	POP	D		;RECALL SECTOR ADDRESS
   124   4AD4 C1        	POP	B	;RECALL NUMBER OF SECTORS REMAINING, AND CURRENT TRK
   125   4AD5 05        	DCR	B		;SECTORS=SECTORS-1
   126   4AD6 CAEF4A    	JZ	GOCPM		;TRANSFER TO CP/M IF ALL HAVE BEEN LOADED
   127                  ;
   128                  ;	MORE	SECTORS REMAIN TO LOAD, CHECK FOR TRACK CHANGE
   129   4AD9 14        	INR	D
   130   4ADA 7A        	MOV	A,D		;SECTOR=27?, IF SO, CHANGE TRACKS
   131   4ADB FE1B      	CPI	27
   132   4ADD DABA4A    	JC	LOAD1		;CARRY GENERATED IF SECTOR<27
   133                  ;
   134                  ;	END OF	CURRENT TRACK,	GO TO NEXT TRACK
   135   4AE0 1601      	MVI	D, 1		;BEGIN WITH FIRST SECTOR OF NEXT TRACK
   136   4AE2 0C        	INR	C		;TRACK=TRACK+1
   137                  ;
   138                  ;	SAVE	REGISTER STATE, AND CHANGE TRACKS
   139   4AE3 C5        	PUSH	B
   140   4AE4 D5        	PUSH	D
   141   4AE5 E5        	PUSH	H
   142   4AE6 CD7D4B    	CALL	SETTRK		;TRACK ADDRESS SET FROM REGISTER C
   143   4AE9 E1        	POP	H
   144   4AEA D1        	POP	D
   145   4AEB C1        	POP	B
   146   4AEC C3BA4A    	JMP	LOAD1		;FOR ANOTHER SECTOR
   147                  ;
   148                  ;	END OF	LOAD OPERATION, SET PARAMETERS AND GO TO CP/M
   149                  GOCPM:
   150   4AEF 3EC3      	MVI	A, 0C3H		;C3 IS A JMP INSTRUCTION
   151   4AF1 320000    	STA	0		;FOR JMP TO WBOOT
   152   4AF4 21034A    	LXI	H, WBOOTE	;WBOOT ENTRY POINT
   153   4AF7 220100    	SHLD	1		;SET ADDRESS FIELD FOR JMP AT 0
   154                  ;
   155   4AFA 320500    	STA	5		;FOR JMP TO BDOS
   156   4AFD 21063C    	LXI	H, BDOS		;BDOS ENTRY POINT
   157   4B00 220600    	SHLD	6		;ADDRESS FIELD OF JUMP AT 5 TO BDOS
   158                  ;
   159   4B03 018000    	LXI	B, 80H		;DEFAULT DMA ADDRESS IS 80H
   160   4B06 CDAD4B    	CALL	SETDMA
   161                  ;
   162   4B09 FB        	EI			;ENABLE THE INTERRUPT SYSTEM
   163   4B0A 3A0400    	LDA	CDISK		;GET CURRENT DISK NUMBER
   164   4B0D 4F        	MOV	C, A		;SEND TO THE CCP
   165   4B0E C30034    	JMP	CCP		;GO TO CP/M FOR FURTHER PROCESSING
   166                  ;
   167                  ;
   168                  ;	SIMPLE I/O HANDLERS (MUST BE FILLED IN BY USER)
   169                  ;	IN EACH CASE, THE ENTRY POINT IS PROVIDED, WITH SPACE RESERVED
   170                  ;	TO INSERT YOUR OWN CODE
   171                  ;
   172                  CONST:	;CONSOLE STATUS, RETURN 0FFH IF CHARACTER READY, 00H IF NOT
   173   4B11           	DS     10H		;SPACE FOR STATUS SUBROUTINE
   174   4B21 3E00      	MVI    A, 00H
   175   4B23 C9        	RET
   176                  ;
   177                  CONIN:	;CONSOLE CHARACTER INTO REGISTER A
   178   4B24           	DS	10H		;SPACE FOR INPUT ROUTINE
   179   4B34 E67F      	ANI	7FH		;STRIP PARITY BIT
   180   4B36 C9        	RET
   181                  ;
   182                  CONOUT:	;CONSOLE CHARACTER OUTPUT FROM REGISTER C
   183   4B37 79        	MOV	A, C		;GET TO ACCUMULATOR
   184   4B38           	DS	10H		;SPACE FOR OUTPUT ROUTINE
   185   4B48 C9        	RET
   186                  ;
   187                  LIST:	;LIST CHARACTER FROM REGISTER C
   188   4B49 79        	MOV	A, C	  	;CHARACTER TO REGISTER A
   189   4B4A C9        	RET		  	;NULL SUBROUTINE
   190                  ;
   191                  LISTST:	;RETURN LIST STATUS (0 IF NOT READY, 1 IF READY)
   192   4B4B AF        	XRA	A	 	;0 IS ALWAYS OK TO RETURN
   193   4B4C C9        	RET
   194                  ;
   195                  PUNCH:	;PUNCH	CHARACTER FROM	REGISTER C
   196   4B4D 79        	MOV	A, C		;CHARACTER TO REGISTER A
   197   4B4E C9        	RET			;NULL SUBROUTINE
   198                  ;
   199                  ;
   200                  READER:	;READER CHARACTER INTO REGISTER A FROM READER DEVICE
   201   4B4F 3E1A      	MVI    A, 1AH		;ENTER END OF FILE FOR NOW (REPLACE LATER)
   202   4B51 E67F      	ANI    7FH		;REMEMBER TO STRIP PARITY BIT
   203   4B53 C9        	RET
   204                  ;
   205                  ;
   206                  ;	I/O DRIVERS FOR THE DISK FOLLOW
   207                  ;	FOR NOW, WE WILL SIMPLY STORE THE PARAMETERS AWAY FOR USE
   208                  ;	IN THE READ AND WRITE	SUBROUTINES
   209                  ;
   210                  HOME:	;MOVE TO THE TRACK 00	POSITION OF CURRENT DRIVE
   211                  ;	TRANSLATE THIS CALL INTO A SETTRK CALL WITH PARAMETER 00
   212   4B54 0E00      	MVI    C, 0		;SELECT TRACK 0
   213   4B56 CD7D4B    	CALL   SETTRK
   214   4B59 C9        	RET			;WE WILL MOVE TO 00 ON FIRST READ/WRITE
   215                  ;
   216                  SELDSK:	;SELECT DISK GIVEN BY REGISTER C
   217   4B5A 210000    	LXI	H, 0000H	;ERROR RETURN CODE
   218   4B5D 79        	MOV	A, C
   219   4B5E 32EF4C    	STA	DISKNO
   220   4B61 FE04      	CPI	4		;MUST BE BETWEEN 0 AND 3
   221   4B63 D0        	RNC			;NO CARRY IF 4, 5,...
   222                  ;	DISK NUMBER IS IN THE PROPER RANGE
   223   4B64           	DS	10		;SPACE FOR DISK SELECT
   224                  ;	COMPUTE PROPER DISK PARAMETER HEADER ADDRESS
   225   4B6E 3AEF4C    	LDA	DISKNO
   226   4B71 6F        	MOV	L, A		;L=DISK NUMBER 0, 1, 2, 3
   227   4B72 2600      	MVI	H, 0		;HIGH ORDER ZERO
   228   4B74 29        	DAD	H		;*2
   229   4B75 29        	DAD	H		;*4
   230   4B76 29        	DAD	H		;*8
   231   4B77 29        	DAD	H		;*16 (SIZE OF EACH HEADER)
   232   4B78 11334A    	LXI	D, DPBASE
   233   4B7B 09        	DAD	0		;HL=,DPBASE (DISKNO*16)
   234   4B7C C9        	RET
   235                  ;
   236                  SETTRK:	;SET TRACK GIVEN BY REGISTER C
   237   4B7D 79        	MOV	A, C
   238   4B7E 32E94C    	STA	TRACK
   239   4B81           	DS	10H		;SPACE FOR TRACK SELECT
   240   4B91 C9        	RET
   241                  ;
   242                  SETSEC:	;SET SECTOR GIVEN BY REGISTER C
   243   4B92 79        	MOV	A, C
   244   4B93 32EB4C    	STA	SECTOR
   245   4B96           	DS	10H		;SPACE FOR SECTOR SELECT
   246   4BA6 C9        	RET
   247                  ;
   248                  ;
   249                  SECTRAN:
   250                  	;TRANSLATE THE SECTOR GIVEN BY BC USING THE
   251                  	;TRANSLATE TABLE GIVEN BY DE
   252   4BA7 EB        	XCHG			;HL=.TRANS
   253   4BA8 09        	DAD	B		;HL=.TRANS (SECTOR)
   254   4BA9 6E        	MOV	L, M		;L=TRANS (SECTOR)
   255   4BAA 2600      	MVI	H, 0		;HL=TRANS (SECTOR)
   256   4BAC C9        	RET			;WITH VALUE IN HL
   257                  ;
   258                  SETDMA:	;SET	DMA ADDRESS GIVEN BY REGISTERS B AND C
   259   4BAD 69        	MOV	L, C		;LOW ORDER ADDRESS
   260   4BAE 60        	MOV	H, B		;HIGH ORDER ADDRESS
   261   4BAF 22ED4C    	SHLD	DMAAD		;SAVE THE ADDRESS
   262   4BB2           	DS	10H		;SPACE FOR SETTING THE DMA ADDRESS
   263   4BC2 C9        	RET
   264                  ;
   265                  READ:	;PERFORM READ OPERATION (USUALLY THIS IS SIMILAR TO WRITE
   266                  ;	SO WE WILL ALLOW SPACE TO SET UP READ COMMAND, THEN USE
   267                  ;	COMMON CODE IN WRITE)
   268   4BC3           	DS	10H		;SET UP READ COMMAND
   269   4BD3 C3E64B    	JMP	WAITIO		;TO PERFORM THE ACTUAL I/O
   270                  ;
   271                  WRITE:	;PERFORM A WRITE OPERATION
   272   4BD6           	DS	10H		;SET UP WRITE COMMAND
   273                  ;
   274                  WAITIO:	;ENTER	HERE FROM READ	AND WRITE TO PERFORM THE ACTUAL I/O
   275                  ;	OPERATION. RETURN A 00H IN REGISTER A IF THE OPERATION COMPLETES
   276                  ;	PROPERLY, AND 0LH IF AN ERROR OCCURS DURING THE READ OR WRITE
   277                  ;
   278                  ;	IN THIS CASE, WE HAVE SAVED THE DISK NUMBER IN 'DISKNO' (0, 1)
   279                  ;			THE TRACK NUMBER IN 'TRACK' (0-76)
   280                  ;			THE SECTOR NUMBER IN 'SECTOR' (1-26)
   281                  ;			THE DMA ADDRESS IN 'DMAAD' (0-65535)
   282   4BE6           	DS	256		;SPACE RESERVED FOR I/O DRIVERS
   283   4CE6 3E01      	MVI	A, 1		;ERROR CONDITION
   284   4CE8 C9        	RET			;REPLACED WHEN FILLED-IN
   285                  ;
   286                  ;	THE REMAINDER OF THE CBIOS IS RESERVED UNINITIALIZED
   287                  ;	DATA AREA, AND DOES NOT NEED TO BE A PART OF THE
   288                  ;	SYSTEM	MEMORY IMAGE (THE SPACE MUST BE AVAILABLE,
   289                  ;	HOWEVER, BETWEEN"BEGDAT" AND"ENDDAT").
   290                  ;
   291   4CE9           TRACK:	DS	2		;TWO BYTES FOR EXPANSION
   292   4CEB           SECTOR:	DS	2		;TWO BYTES FOR EXPANSION
   293   4CED           DMAAD:	DS	2		;DIRECT MEMORY ADDRESS
   294   4CEF           DISKNO:	DS	1		;DISK NUMBER 0-15
   295                  ;
   296                  ;	SCRATCH RAM AREA FOR BDOS USE
   297   4CF0 =         BEGDAT	EQU	$	 	;BEGINNING OF DATA AREA
   298   4CF0           DIRBF:	DS	128	 	;SCRATCH DIRECTORY AREA
   299   4D70           ALL00:	DS	31	 	;ALLOCATION VECTOR 0
   300   4D8F           ALL01:	DS	31	 	;ALLOCATION VECTOR 1
   301   4DAE           ALL02:	DS	31	 	;ALLOCATION VECTOR 2
   302   4DCD           ALL03:	DS	31	 	;ALLOCATION VECTOR 3
   303   4DEC           CHK00:	DS	16		;CHECK VECTOR 0
   304   4DFC           CHK01:	DS	16		;CHECK VECTOR 1
   305   4E0C           CHK02:	DS	16	 	;CHECK VECTOR 2
   306   4E1C           CHK03:	DS	16	 	;CHECK VECTOR 3
   307                  ;
   308   4E2C =         ENDDAT	EQU	$	 	;END OF DATA AREA
   309   013C =         DATSIZ	EQU	$-BEGDAT;	;SIZE OF DATA AREA
   310   4E2C           	END
ALL00            4D70    45   299#
ALL01            4D8F    50   300#
ALL02            4DAE    55   301#
ALL03            4DCD    60   302#
BDOS             3C06    10#  156 
BEGDAT           4CF0   297#  309 
BIAS             0000     8#    9 
BIOS             4A00    11#   15 
BOOT             4A9C    20    86#
CCP              3400     9#   10    11    16   103   165 
CDISK            0004    12#   89   163 
CHK00            4DEC    45   303#
CHK01            4DFC    50   304#
CHK02            4E0C    55   305#
CHK03            4E1C    60   306#
CONIN            4B24    23   177#
CONOUT           4B37    24   182#
CONST            4B11    22   172#
DATSIZ           013C   309#
DIRBF            4CF0    44    49    54    59   298#
DISKNO           4CEF   219   225   294#
DMAAD            4CED   261   293#
DPBASE           4A33    42#  232 
DPBLK            4A8D    44    49    54    59    71#
ENDDAT           4E2C   308#
GOCPM            4AEF    90   126   149#
HOME             4B54    28    96   210#
IOBYTE           0003    13#   88 
LIST             4B49    25   187#
LISTST           4B4B    35   191#
LOAD1            4ABA   104#  132   146 
MSIZE            0014     3#    8 
NSECTS           002C    16#   98 
PUNCH            4B4D    26   195#
READ             4BC3    33   115   265#
READER           4B4F    27   200#
SECTOR           4CEB   244   292#
SECTRAN          4BA7    36   249#
SELDSK           4B5A    29    95   216#
SETDMA           4BAD    32   112   160   258#
SETSEC           4B92    31   109   242#
SETTRK           4B7D    30   142   213   236#
TRACK            4CE9   238   291#
TRANS            4A73    42    47    52    57    63#
WAITIO           4BE6   269   274#
WBOOT            4AA6    21    92#  117 
WBOOTE           4A03    21#  152 
WRITE            4BD6    34   271#
