;  CP/NET-86 LOADER
;
;  1983.8.31.	VER.1.00
;
;  EQUATIONS OF DATA
;
LF	EQU	0AH			;LINE FEED
CR	EQU	0DH			;CARRIAGE RETURN
;
BDOS	EQU	224			;BODS INTERRUPT NUMBER
SCTLNG	EQU	128			;SECTOR LENGTH
;
VBDOS	EQU	BDOS*4			;VECTOR OF BDOS INTERRUPT
BSBIOS	EQU	250H			;BIAS TO BIOS
MINSIZ	EQU	800H			;MINIMUM REQUIRED SPACE
MAXCPM	EQU	0C00H			;MAXIMUM CP/M SIZE
;
;  EQUATIONS OF BDOS FUNCTION
;
CRESET	EQU	0			;SYSTEM RESET
CCONOT	EQU	2			;CONSOLE OUT
CBUFPR	EQU	9			;BUFFERED STRING PRINT
CGETVR	EQU	12			;GET VERSION NUMBER
COPEN	EQU	15			;OPEN FILE
CREAD	EQU	20			;READ FILE
CSTDMA	EQU	26			;SET DMA OFFSET
CDBIOS	EQU	50			;DIRECT BIOS CALL
CSTDMS	EQU	51			;SET DMA SEGMENT
CGTMXM	EQU	53			;GET MAXIMUM MEMORY
;
;
	ORG	100H
;
	JMP	START
;
;
	DB	'COPYRIGHT (C) 1983,'
	DB	' XYZ (DIGITAL RESEARCH)'
;
;
START:
	MOV	AX,CS
	MOV	SS,AX
	MOV	SP,OFFSET STACK		;SET STACK
	XOR	DX,DX
	MOV	CL,CGETVR
	INT	BDOS			;GET VERSION NUMBER
	MOV	CX,OFFSET CARLOD
	AND	AX,200H
	JNZ	ERROR			;ALREADY LOADED
	CALL	GETMRG			;GET LOADING MEMORY REGION
	MOV	CX,OFFSET CSTUP
	CALL	BUFPRN			;OUT TABLE TOP
	XOR	DX,DX
	MOV	CX,OFFSET CCCP
	CALL	DSPLIN			;OUT CCP LOCATION
	XOR	DX,DX
	MOV	ES,DX
	MOV	DX,ES:WORD PTR .VBDOS	;GET OFFSET OF BDOS
	MOV	CL,4
	SHR	DX,CL			;GET BDOS BIAS
	MOV	CX,OFFSET CBDOS
	CALL	DSPLIN			;OUT BDOS LOCATION
	MOV	DX,BSBIOS		;BIOS TOP
	MOV	CX,OFFSET CBIOS
	CALL	DSPLIN			;OUT BIOS LOCATION
	MOV	DX,LODOFF
	MOV	CX,OFFSET CCCPN
	CALL	LOAD			;LOAD CCPN
	MOV	NDOSOF,DX		;SAVE NDOS TOP
	MOV	CX,OFFSET CNDOS
	CALL	LOAD			;LOAD NDOS
	MOV	CX,OFFSET CSNIOS
	CALL	LOAD			;LOAD SNIOS
	MOV	CX,OFFSET CTPA
	CALL	DSPLIN			;TPA LOCATION
	MOV	CX,OFFSET CLEND
	CALL	BUFPRN			;OUT LOADING END COMMENT
	MOV	AX,NDOSOF
	MOV	CL,4
	SHL	AX,CL
	ADD	AX,3
	MOV	NDOSEN,AX		;SET NDOS COLD START ENTRY OFFSET
	JMPF	DWORD PTR NDOSEN	;TO NDOS
;
;  ERROR END
;  INPUT
;  CX:COMMENT POINT
;
ERROR:					;ERROR END
	CALL	BUFPRN			;OUT ERROR COMMENT
	MOV	CL,CRESET
	INT	BDOS			;RETURN TO SYSTEM
;
;  GET MEMORY REGION FOR CP/NET SYSTEM
;
GETMRG:
	MOV	DX,OFFSET WKMCB
	MOV	CL,CGTMXM
	INT	BDOS			;GET MAXIMUM MEMORY
	MOV	CX,OFFSET CNOAVL
	OR	AL,AL
	JNZ	ERROR			;NO AVAILABLE MEMORY
	MOV	CL,CDBIOS
	MOV	DX,OFFSET WKBIOS
	INT	BDOS			;GET MEMORY REGION TABLE
	INC	BX
	MOV	DX,ES:[BX]		;GET TOP REGION
	MOV	CX,OFFSET CNOAVL
	CMP	DX,WKMCB
	JNZ	ERROR			;NOT TOP  NEED TOP REGION FOR CP/NET
	MOV	AX,WKMCB+2
	CMP	AX,MINSIZ
	JC	ERROR			;TOO SMALL
	XOR	AX,AX
	MOV	ES,AX			;INTERRUPT VECTOR PAGE
	MOV	DX,ES:WORD PTR .VBDOS+2	;GET DOS SEGMENT
	MOV	DOSSGM,DX		;SAVE SEGMENT
	MOV	AX,WKMCB		;GET AVAILABLE TOP
	SUB	AX,DX
	ADD	AX,15
	AND	AX,0FFF0H		;TO PAGE BOUNDARY
	CMP	AX,MAXCPM
	JNC	ERROR			;CP/M BASIC LENGTH TOO LONG
	MOV	LODOFF,AX		;SAVE OFFSET
	RET
;
;  ERROR OF LOADING
;
ERLOAD:
	MOV	CX,OFFSET CLERR
	JMP	ERROR
;
;  LOAD ONE PROGRAM
;  INPUT
;  DX:LOADING TOP PARAGRAPH
;  CX:FILE NAME POINTER
;  OUTPUT
;  DX:NEXT PARAGRAPH
;
LOAD:
	PUSH	DX
	PUSH	CX
	CALL	CRLF
	POP	CX
	PUSH	CX
	CALL	BUFPRN			;OUT FILE NAME
	MOV	AX,DS
	MOV	ES,AX
	POP	SI
	MOV	DI,OFFSET WKFCB
	CLD
	XOR	AX,AX
	STOSB				;CLEAR ENTRY TYPE
	MOV	CX,11
	REP	MOVSB			;SET FILE NAME TO FCB
	MOV	CL,21
	REP	STOSB			;CLEAR LEFT AREA
	MOV	DX,OFFSET WKFCB
	MOV	CL,COPEN
	INT	BDOS			;OPEN FILE
	INC	AL
	JZ	ERLOAD			;FILE NOT FOUND
	MOV	DX,CS
	MOV	CL,CSTDMS
	INT	BDOS			;SET DMA SEGMENT
	MOV	DX,OFFSET RDWORK
	MOV	CL,CSTDMA
	INT	BDOS			;SET DMA OFFSET TO READ WORK
	CALL	READ			;READ ONE SECTOR
	MOV	BX,OFFSET RDWORK+1
	MOV	DX,[BX]			;GET CODE LENGTH
	MOV	AX,3[BX]		;GET DATA LENGTH
	ADD	AX,DX			;GET TOTAL LENGTH
	MOV	CODLNG,DX		;SAVE CODE LENGTH
	MOV	CL,4
	ADD	AX,15
	SHR	AX,CL			;GET BY PARAHRAPH
	POP	BX			;GET CURRENT TOP
	MOV	TOPPGH,BX		;SAVE TOP
	ADD	AX,BX
	ADD	AX,15
	AND	AX,0FFF0H		;GET NEXT PAGE TOP
	MOV	NXTPGH,AX		;SAVE NEXT PARAGRAPH
	MOV	CL,4
	SHL	BX,CL
	MOV	LODTOP,BX
	ADD	DX,127
	MOV	CL,7
	SHR	DX,CL			;GET SECTOR COUNT
	MOV	DI,BX			;SET DESTINATION POINTER
	PUSH	DX
	PUSH	DI
	CALL	READ			;DUMMY PASS READ
	POP	DI
	POP	DX
LOADLP:					;ONE SECTOR LOAD LOOP
	PUSH	DX
	PUSH	DI
	CALL	READ			;REDA ONE SECTOR
	POP	DI
	MOV	SI,OFFSET RDWORK
	MOV	ES,DOSSGM		;DESTINATION SEGMENT
	MOV	CX,SCTLNG
	CLD
	REP	MOVSB			;TO DESTINATION AREA
	POP	DX
	DEC	DX
	JNZ	LOADLP			;TO NEXT SECTOR
	MOV	DX,CODLNG		;GET CODE LENGTH
	MOV	AX,DX
	AND	AX,7FH			;GET OFFSET IN SECTOR
	MOV	SI,OFFSET RDWORK
	ADD	SI,AX			;GET DATA POINT
	MOV	BX,LODTOP		;LOADED DATA TOP
	MOV	CL,3
	SHL	AX,CL
	MOV	CX,AX			;GET RELOCATION COUNT
	MOV	AH,BH			;GET RELOCATION BIAS
LOADRL:					;RELOCATION LOOP
	TEST	CL,7
	JNZ	LOADRB			;NOT BYTE BOUNDARY
	TEST	CX,3FFH
	JNZ	LOADRS			;NOT SECTOR BOUNDARY
	PUSH	AX			;TO NEXT SECTOR
	PUSH	BX
	PUSH	DX
	PUSH	ES
	CALL	READ			;READ TO WORK
	POP	ES
	POP	DX
	POP	BX
	POP	AX
	XOR	CX,CX			;CLEAR COUNT
	MOV	SI,OFFSET RDWORK	;WORK TOP
	CLD
LOADRS:
	LODSB				;GET ONE BYTE RELOCATION DATA
LOADRB:
	INC	CX
	ROL	AL,1
	JNC	LOADRA			;ABSOLUTE
	ADD	ES:[BX],AH		;RELOCATE
LOADRA:
	INC	BX			;POINTER TO NEXT
	DEC	DX			;DOWN LENGTH COUNT
	JNZ	LOADRL			;TO NEXT DATA
	MOV	AX,TOPPGH
	PUSH	AX
	MOV	CL,4
	SHL	AX,CL			;GET OFFSET
	MOV	CX,AX
	CALL	LOCPRS			;OUT OFFSET
	POP	CX
	ADD	CX,DOSSGM
	CALL	LOCPR			;OUT TOP
	MOV	DX,NXTPGH		;GET NEXT PARAGRAPH
LOADEN:
	RET
;
;  READ ONE SECTOR
;
READ:
	MOV	DX,OFFSET WKFCB
	MOV	CL,CREAD
	INT	BDOS			;READ ONE SECTOR
	OR	AL,AL
	JZ	LOADEN			;OK
	JMP	ERLOAD			;NO DATA OR SO
;
;  DISPLAY LINE
;  INPUT
;  DX:PARAGRAPH OFFSET OF TOP
;  CX:NAME COMMENT POINTER
;
DSPLIN:
	PUSH	DX
	PUSH	CX
	CALL	CRLF
	POP	CX
	CALL	BUFPRN			;OUT NAME
	POP	AX
	PUSH	AX
	MOV	CL,4
	SHL	AX,CL
	MOV	CX,AX
	CALL	LOCPRS			;OUT OFFSET
	POP	CX
	ADD	CX,DOSSGM
	JMPS	LOCPR			;OUT LOCATION
;
;  OUT LOCATION
;  INPUT
;  CX:OFFSET
;
LOCPRS:
	CALL	LOCPRD			;OUT NUMBER PART
	MOV	CL,'H'
	JMP	CONOUT
;
;  OUT LOCATION
;  INPUT
;  CX:PARAGRAPH DATA
;
LOCPR:
	CALL	LOCPRD			;OUT NUMBER PART
	MOV	CL,'0'
	CALL	CONOUT
	MOV	CL,'H'
	JMP	CONOUT
;
;  OUT HEXADECIMAL WORD DATA
;  INPUT
;  CX:DATA
;
LOCPRD:
	PUSH	CX
	MOV	CL,' '
	CALL	CONOUT
	MOV	CL,' '
	CALL	CONOUT
	POP	CX
	PUSH	CX
	MOV	CL,CH
	CALL	HXPRN			;PRINT HIGHER
	POP	CX			;TO PRINT LOSER
;
;  PRINT BY HEXADECIMAL
;  INPUT
;  CL:DATA
;
HXPRN:
	PUSH	CX
	SHR	CL,1
	SHR	CL,1
	SHR	CL,1
	SHR	CL,1
	CALL	HXPRH			;PRINT HIGHER NIBBLE
	POP	CX
HXPRH:
	AND	CL,0FH
	ADD	CL,'0'
	CMP	CL,'9'+1
	JC	CONOUT			;0 TO 9
	ADD	CL,7
	JMPS	CONOUT			;A TO F
;
;  CONSOLE OUT
;  INPUT
;  CL:CODE
;
CONOUT:
	PUSH	AX
	MOV	DL,CL
	MOV	CL,CCONOT
	INT	BDOS
	POP	AX
	RET
;
;  PRINT BUFFERED STRING
;  INPUT
;  CX:STRING POINTER
;
BUFPRN:
	MOV	DX,CX
	MOV	CL,CBUFPR
	INT	BDOS
	RET
;
;  CARRIAGE RETURN & LINE FEED
;
CRLF:
	MOV	CL,CR
	CALL	CONOUT
	MOV	CL,LF
	JMPS	CONOUT
;
DAREA	EQU	$
;
	DSEG
	ORG	OFFSET DAREA
;
;  COMENTS
;
CARLOD	DB	CR,LF,'CP/NET-86 IS ALREADY LOADED.$'
CSTUP	DB	CR,LF,LF,'CP/NET-86  VER.1.00 LOADER'
	DB	CR,LF,'==========================$'
CNOAVL	DB	CR,LF,'NO AVAILABLE MEMORY FOR CP/NET-86$'
CLERR	DB	'		LOADING ERROR OF THIS FILE$'
CLEND	DB	CR,LF,'CP/NET-86 LOADING COMPLETE.',CR,LF,'$'
;
CCCP	DB	'CCP        $'
CBDOS	DB	'BDOS       $'
CBIOS	DB	'BIOS       $'
CCCPN	DB	'CCPN    SYS$'
CNDOS	DB	'NDOS    SYS$'
CSNIOS	DB	'SNIOS   SYS$'
CTPA	DB	'TPA        $'
;
;  WORK AREA
;
;  MEMORY CONTROL BLOCK
;
WKMCB	DW	0			;BASE
	DW	0FFF0H			;LENGTH
	DB	0			;EXTENT
;
;  DIRECT BIOS CALL WORK
;
WKBIOS	DB	18			;GET MEMORY REGION TABLE
	DW	0			;INPUT PARAMETER  NOT USED
	DW	0
;
LODOFF	RW	1			;LOAD OFFSET BY PARAGRAPH
NDOSOF	RW	1			;NDOS OFFSET BY PARAGRAPH
;
NDOSEN	RW	1			;NDOS ENTRY
DOSSGM	RW	1			;DOS SEGMENT
;
;  LOADER WORK
;
WKFCB	RB	33			;FCB
RDWORK	RB	128			;WORKING FOR ONE SECTOR READ
CODLNG	RW	1			;CODE AREA LENGTH
TOPPGH	RW	1			;TOP PARAGRAPH
NXTPGH	RW	1			;NEXT PARAGRAPH
LODTOP	RW	1			;LOADING TOP
;
;
	RS	64
STACK:
	DB	0
;
;
	END
