You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

507 lines
13 KiB

TITLE 'SYSGEN - SYSTEM GENERATION PROGRAM 8/79'
; SYSTEM GENERATION PROGRAM, VERSION FOR ROMWBW
VERS EQU 20 ; X.X
;
; COPYRIGHT (C) DIGITAL RESEARCH
; 1976, 1977, 1978, 1979
;
NDISKS EQU 16 ; NUMBER OF DISK DRIVES
SECSIZ EQU 128 ; SIZE OF EACH SECTOR
LOG2SEC EQU 7 ; LOG 2 SECSIZ
;
FCB EQU 05CH ; DEFAULT FCB LOCATION
FCBCR EQU FCB+32 ; CURRENT RECORD LOCATION
TPA EQU 0100H ; TRANSIENT PROGRAM AREA
LOADP EQU 900H ; LOAD POINT FOR SYSTEM DURING LOAD/STORE
BDOS EQU 5 ; DOS ENTRY POINT
BOOT EQU 0 ; JMP TO 'BOOT' TO REBOOT SYSTEM
CONI EQU 1 ; CONSOLE INPUT FUNCTION
CONO EQU 2 ; CONSOLE OUTPUT FUNCTION
OPENF EQU 15 ; DISK OPEN FUNCTION
DREADF EQU 20 ; DISK READ FUNCTION
;
CR EQU 0DH ; CARRIAGE RETURN
LF EQU 0AH ; LINE FEED
STKSIZE EQU 16 ; SIZE OF LOCAL STACK
;
WBOOT EQU 1 ; ADDRESS OF WARM BOOT (OTHER PATCH ENTRY
;
ORG TPA ; TRANSIENT PROGRAM AREA
JP START
DB 'COPYRIGHT (C) 1978, DIGITAL RESEARCH '
;
; UTILITY SUBROUTINES
;
GETCHAR:
; READ CONSOLE CHARACTER TO REGISTER A
LD C,CONI
CALL BDOS
; CONVERT TO UPPER CASE BEFORE RETURN
CP 'A' OR 20H
RET C ; RETURN IF BELOW LOWER CASE A
CP ('Z' OR 20H) + 1
RET NC ; RETURN IF ABOVE LOWER CASE Z
AND 5FH
RET
;
PUTCHAR:
; WRITE CHARACTER FROM A TO CONSOLE
LD E,A
LD C,CONO
CALL BDOS
RET
;
CRLF: ; SEND CARRIAGE RETURN, LINE FEED
LD A,CR
CALL PUTCHAR
LD A,LF
CALL PUTCHAR
RET
;
CRMSG: ; PRINT MESSAGE ADDRESSED BY H,L TIL ZERO
; WITH LEADING CRLF
PUSH HL
CALL CRLF
POP HL ; DROP THRU TO OUTMSG0
OUTMSG:
LD A,(HL)
OR A
RET Z
; MESSAGE NOT YET COMPLETED
PUSH HL
CALL PUTCHAR
POP HL
INC HL
JP OUTMSG
;
DREAD: ; DISK READ FUNCTION VIA BDOS
LD C,DREADF
JP BDOS
;
OPEN: ; FILE OPEN FUNCTION VIA BDOS
LD C,OPENF
JP BDOS
;
; READ IMAGE DIRECTLY FROM DISK SYSTEM TRACKS USING CBIOS
; DISK NUMBER MUST BE IN (ACTDSK)
;
RDDSK:
; FORCE RETURN TO GO THROUGH DISK RESET
LD HL,RESDSK ; LOAD ADDRESS OF RESET DISK ROUTINE
PUSH HL ; AND PUT IT ON THE STACK
; SET DRIVE FOR SUBSEQUENT READS
CALL SETDSK ; SETUP DISK SPECIFIED IN A
RET NZ ; ABORT ON ERROR
; SET FUNCTION TO READ
LD HL,(CBFTBL) ; GET ADDRESS OF CBIOS FUNCTION TABLE
LD A,027H ; $27 IS CBIOS READ ENTRY OFFSET
CALL ADDHL ; SET HL TO RESULTANT ENTRY POINT
LD (ACTFNC),HL ; SAVE IT
; READ THE HEADER
LD A,12 ; START WITH 1536 BYTE HEADER (12 RECORDS)
LD (RECCNT),A ; INITIALIZE RECORD COUNTER
CALL RWDSK ; READ THE HEADER
RET NZ ; ABORT ON ERROR
; CHECK HEADER AND GET IMAGE SIZE
CALL CHKHDR ; CHECK INTEGRITY, HL = IMAGE SIZE ON RETURN
RET NZ ; ABORT ON ERROR
; CONVERT IMAGE SIZE TO COUNT OF 128-BYTE RECORDS
LD B,7 ; RIGHT SHIFT 7 BITS TO GET 128 BYTE RECORD COUNT
RDDSK1: SRL H ; SHIFT RIGHT MSB
RR L ; SHIFT LSB W/ CARRY FROM MSB
DJNZ RDDSK1 ; LOOP TILL DONE
; SET THE NUMBER OF RECORDS PENDING TO READ
LD A,L ; RECORD COUNT TO A
LD (RECCNT),A ; SET REMAINING RECORDS TO READ
; SAVE THE TOTAL IMAGE SIZE (INCLUDING HEADER) FOR LATER
ADD A,12 ; ADD THE HEADER RECORDS BACK
LD (IMGSIZ),A ; AND SAVE THE TOTAL IMAGE SIZE (IN RECORDS)
; READ THE REMAINING SYSTEM IMAGE RECORDS
CALL RWDSK ; FINISH UP
RET NZ ; ABORT ON ERROR
; PERFORM BDOS DISK RESET (CRITICAL SINCE WE MUCKED WITH CBIOS)
LD C,0DH ; BDOS RESET DISK
CALL BDOS ; DO IT
; RETURN
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; WRITE IMAGE DIRECTLY TO DISK SYSTEM TRACKS USING CBIOS
; DISK NUMBER MUST BE IN (ACTDSK)
;
WRDSK:
; FORCE RETURN TO GO THROUGH DISK RESET
LD HL,RESDSK ; LOAD ADDRESS OF RESET DISK ROUTINE
PUSH HL ; AND PUT IT ON THE STACK
; SET DRIVE FOR SUBSEQUENT WRITES
CALL SETDSK ; SETUP DISK SPECIFIED IN A
RET NZ ; ABORT ON ERROR
; SET FUNCTION TO WRITE
LD HL,(CBFTBL) ; GET ADDRESS OF CBIOS FUNCTION TABLE
LD A,02AH ; $2A IS CBIOS WRITE ENTRY OFFSET
CALL ADDHL ; SET HL TO RESULTANT ENTRY POINT
LD (ACTFNC),HL ; SAVE IT
; SETUP THE RECORD COUNT TO WRITE
LD A,(IMGSIZ) ; GET PREVIOUSLY RECORDED IMAGE SIZE
LD (RECCNT),A ; SAVE IT AS PENDING RECORD COUNT
; WRITE THE IMAGE
CALL RWDSK ; WRITE THE IMAGE
RET NZ ; ABORT ON ERROR
; RETURN
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; PERFORM BDOS DISK RESET
; REQUIRED AFTER MAKING DIRECT CBIOS DISK CALLS
;
RESDSK:
; PERFORM BDOS DISK RESET
PUSH AF ; PRESERVE STATUS
LD C,0DH ; BDOS RESET DISK
CALL BDOS ; DO IT
POP AF ; RESTORE STATUS
RET
;
; SETUP FOR CBIOS DISK ACCESS
;
SETDSK:
; SELECT DISK
LD A,(ACTDSK) ; GET ACTIVE DISK
LD C,A ; MOVE TO C
LD E,0 ; TREAT AS FIRST SELECT
CALL CBIOS ; INVOKE CBIOS WITH...
DB 01BH ; SELDSK ENTRY OFFSET
; CHECK RETURN (SETS HL TO DPH ADDRESS)
LD A,H
OR L
JP Z,ERRSEL ; HL == 0 IS SELECT ERROR
; SET HL TO DPB ADDRESS
LD DE,10 ; DPB ADDRESS IS 10 BYTES INTO DPH
ADD HL,DE ; HL := ADDRESS OF DPB POINTER
LD A,(HL) ; DEREFERENCE...
INC HL
LD H,(HL)
LD L,A ; HL := ADDRESS OF DPB
; EXTRACT SECTORS PER TRACK FROM FIRST WORD OF DPB
LD C,(HL)
INC HL
LD B,(HL) ; BC := SECTORS PER TRACK
LD (ACTSPT),BC ; SAVE IT
; ENSURE THERE ARE SYSTEM TRACKS (VERIFY THAT OFFSET FIELD IN DPB IS NOT ZERO)
LD DE,12 ; OFFSET FIELD IS 12 BYTES INTO DPB
ADD HL,DE ; POINT TO OFFSET FIELD IN DPB
LD A,(HL) ; LOAD FIRST BYTE IN A
INC HL ; POINT TO SECOND BYTE
OR (HL) ; OR WITH FIRST BYTE
JP Z,ERRSYS ; IF ZERO, ABORT (NO SYSTEM TRACKS)
; INITIALIZE FOR I/O
LD HL,0
LD (ACTTRK),HL ; ACTIVE TRACK := 0
LD (ACTSEC),HL ; ACTIVE SECTOR := 0
LD HL,LOADP
LD (BUFPTR),HL ; RESET BUFFER POINTER
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; READ OR WRITE (RECCNT) SECTORS TO/FROM DISK VIA CBIOS
;
RWDSK:
; SETUP TO READ/WRITE A SECTOR
LD BC,(ACTTRK) ; GET ACTIVE TRACK
CALL CBIOS ; INVOKE CBIOS WITH...
DB 01EH ; SETTRK ENTRY OFFSET
LD BC,(ACTSEC) ; GET ACTIVE SECTOR
CALL CBIOS ; INVOKE CBIOS WITH...
DB 021H ; SETSEC ENTRY OFFSET
LD BC,(BUFPTR) ; GET ACTIVE BUFFER POINTER
CALL CBIOS ; INVOKE CBIOS WITH...
DB 024H ; SETDMA ENTRY OFFSET
; READ/WRITE SECTOR
LD A,(RECCNT) ; GET THE PENDING RECORD COUNT
DEC A ; LAST RECORD?
LD C,2 ; ALLOW CACHED WRITES BY DEFAULT
JR NZ,RWDSK1 ; NOT LAST RECORD, CONTINUE
LD C,1 ; LAST RECORD, NO CACHING PLEASE
RWDSK1: LD HL,(ACTFNC) ; LOAD THE CBIOS FUNCTION VECTOR
CALL JPHL ; INDIRECT CALL (READ OR WRITE)
OR A ; SET FLAGS ON RETURN CODE
JP NZ,ERRIO ; IF NOT ZERO, ERROR ABORT
; ADJUST BUFFER POINTER
LD HL,(BUFPTR) ; GET BUFFER POINTER
LD DE,128 ; RECORD LENGTH IS 128 BYTES
ADD HL,DE ; ADJUST BUFFER PTR FOR NEXT RECORD
LD (BUFPTR),HL ; SAVE IT
; NEXT SECTOR
LD HL,(ACTSEC) ; CURRENT SECTOR
INC HL ; INCREMENT SECTOR
LD (ACTSEC),HL ; SAVE IT
; CHECK FOR END OF TRACK
LD DE,(ACTSPT) ; GET CURRENT SECTORS PER TRACK
OR A ; CLEAR CF
SBC HL,DE ; CURRENT TRACK == SECTORS PER TRACK?
JR NZ,RWDSK2 ; NO, SKIP TRACK CHANGE
; NEXT TRACK
LD HL,0
LD (ACTSEC),HL ; CURRENT SECTOR := 0
LD HL,ACTTRK ; POINT TO TRACK VARIABLE
INC (HL) ; INCREMENT TRACK
; CHECK PENDING RECORD COUNT AND LOOP OR RETURN
RWDSK2: LD HL,RECCNT
DEC (HL) ; DECREMENT PENDING RECORD COUNT
RET Z ; IF ZERO, DONE, RETURN WITH Z SET
JR RWDSK ; OTHERWISE, LOOP
;
JPHL: JP (HL) ; INDIRECT JUMP
;
; VERIFY SYSTEM IMAGE HEADER IN BUF BY CHECKING THE EXPECTED SIGNATURE.
; COMPUTE AND RETURN IMAGE SIZE (BASED ON HEADER VALUES) IN HL.
; NZ SET IF SIGNATURE ERROR.
;
CHKHDR:
; CHECK SIGNATURE
LD HL,(LOADP+580H) ; GET SIGNATURE
LD DE,0A55AH ; SIGNATURE VALUE
OR A ; CLEAR CF
SBC HL,DE ; COMPARE
JP NZ,ERRSIG ; INVALID SIGNATURE
; COMPUTE THE IMAGE SIZE (DOES NOT INCLUDE SIZE OF HEADER)
LD HL,(LOADP+5FCH) ; GET CPM_END
LD DE,(LOADP+5FAH) ; GET CPM_LOC
OR A ; CLEAR CF
SBC HL,DE ; IMAGE SIZE := CPM_END - CPM_LOC
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; INVOKE CBIOS FUNCTION
; THE CBIOS FUNCTION OFFSET MUST BE STORED IN THE BYTE
; FOLLOWING THE CALL INSTRUCTION. EX:
; CALL CBIOS
; DB 0CH ; OFFSET OF CONOUT CBIOS FUNCTION
;
CBIOS:
EX (SP),HL
LD A,(HL) ; GET THE FUNCTION OFFSET
INC HL ; POINT PAST VALUE FOLLOWING CALL INSTRUCTION
EX (SP),HL ; PUT ADDRESS BACK AT TOP OF STACK AND RECOVER HL
LD HL,(CBFTBL) ; ADDRESS OF CBIOS FUNCTION TABLE TO HL
CALL ADDHL ; DETERMINE SPECIFIC FUNCTION ADDRESS
JP (HL) ; INVOKE CBIOS
;
; ADD THE VALUE IN A TO HL (HL := HL + A)
;
ADDHL:
ADD A,L ; A := A + L
LD L,A ; PUT RESULT BACK IN L
RET NC ; IF NO CARRY, WE ARE DONE
INC H ; IF CARRY, INCREMENT H
RET ; AND RETURN
;
; START OF PROGRAM
;
START:
LD SP,STACK ; SET LOCAL STACK POINTER
LD HL,SIGNON
CALL CRMSG
; LOCATE CBIOS FUNCTION TABLE ADDRESS
LD HL,(BOOT+1) ; LOAD ADDRESS OF CP/M RESTART VECTOR
LD DE,-3 ; ADJUSTMENT FOR START OF TABLE
ADD HL,DE ; HL NOW HAS START OF TABLE
LD (CBFTBL),HL ; SAVE IT
; CHECK FOR DEFAULT FILE LOAD INSTEAD OF GET
LD A,(FCB+1); BLANK IF NO FILE
CP ' '
JP Z,GETSYS ; SKIP TO GET SYSTEM MESSAGE IF BLANK
LD DE,FCB ; TRY TO OPEN IT
CALL OPEN ;
INC A ; 255 BECOMES 00
JP NZ,RDOK ; OK TO READ IF NOT 255
; FILE NOT PRESENT, ERROR AND REBOOT
LD HL,NOFILE
CALL CRMSG
JP REBOOT
;
; FILE PRESENT - READ TO LOAD POINT
;
RDOK:
XOR A
LD (FCBCR),A; CURRENT RECORD = 0
; PRE-READ AREA FROM TPA TO LOADP
LD C,(LOADP-TPA)/SECSIZ
PRERD: ; PRE-READ FILE
PUSH BC ; SAVE COUNT
LD DE,FCB ; INPUT FILE CONTROL COUNT
CALL DREAD ; ASSUME SET TO DEFAULT BUFFER
POP BC ; RESTORE COUNT
OR A
JP NZ,BADRD ; CANNOT ENCOUNTER END-OF FILE
DEC C ; COUNT DOWN
JP NZ,PRERD ; FOR ANOTHER SECTOR
;
; SECTORS SKIPPED AT BEGINNING OF FILE
;
LD HL,LOADP
RDINP:
PUSH HL
LD B,H
LD C,L ; READY FOR DMA
CALL CBIOS ; INVOKE CBIOS WITH...
DB 024H ; SETDMA ENTRY OFFSET
LD DE,FCB ; READY FOR READ
CALL DREAD ;
POP HL ; RECALL DMA ADDRESS
OR A ; 00 IF READ OK
JP NZ,PUTSYS ; ASSUME EOF IF NOT.
; MORE TO READ, CONTINUE
LD DE,SECSIZ
ADD HL,DE ; HL IS NEW LOAD ADDRESS
JP RDINP
;
BADRD: ; EOF ENCOUNTERED IN INPUT FILE
LD HL,BADFILE
CALL CRMSG
JP REBOOT
;
GETSYS:
CALL CRLF
LD HL,ASKGET ; GET SYSTEM?
CALL CRMSG
CALL GETCHAR
CP CR
JP Z,PUTSYS ; SKIP IF CR ONLY
;
SUB 'A' ; NORMALIZE DRIVE NUMBER
CP NDISKS ; VALID DRIVE?
JP C,GETC ; SKIP TO GETC IF SO
; INVALID DRIVE NUMBER
CALL BADDISK
JP GETSYS ; TO TRY AGAIN
;
GETC:
; SELECT DISK GIVEN BY REGISTER A
ADD A,'A'
LD (GDISK),A; TO SET MESSAGE
SUB 'A'
LD (ACTDSK),A ; SAVE ACTIVE DISK NO
; ; GETSYS, SET RW TO READ AND GET THE SYSTEM
CALL CRLF
LD HL,GETMSG
CALL OUTMSG
CALL GETCHAR
CP CR
JP NZ,REBOOT
CALL CRLF
CALL RDDSK
JP NZ,GETSYS
LD HL,DONE
CALL OUTMSG
;
; PUT SYSTEM
;
PUTSYS:
CALL CRLF
LD HL,ASKPUT
CALL CRMSG
CALL GETCHAR
CP CR
JP Z,REBOOT
SUB 'A'
CP NDISKS
JP C,PUTC
; INVALID DRIVE NAME
CALL BADDISK
JP PUTSYS ; TO TRY AGAIN
;
PUTC: ; SET DISK FROM REGISTER C
ADD A,'A'
LD (PDISK),A ; MESSAGE SET
SUB 'A'
LD (ACTDSK),A ; SAVE ACTIVE DISK NO
; PUT SYSTEM
LD HL,PUTMSG
CALL CRMSG
CALL GETCHAR
CP CR
JP NZ,REBOOT
CALL CRLF
CALL WRDSK
JP NZ,PUTSYS
LD HL,DONE
CALL OUTMSG
JP PUTSYS ; FOR ANOTHER PUT OPERATION
;
REBOOT:
CALL CRLF
JP BOOT
;
ERRSEL:
LD HL,SELMSG
JP ERR
;
ERRSYS:
LD HL,SYSMSG
JP ERR
;
ERRIO:
LD HL,IOMSG
JP ERR
;
ERRSIG:
LD HL,SIGMSG
JP ERR
;
ERR:
CALL OUTMSG
OR A,0FFH
RET
;
BADDISK:;BAD DISK NAME
LD HL,QDISK
CALL CRMSG
RET
;
; DATA AREAS
; MESSAGES
;
SIGNON: DB 'ROMWBW SYSGEN VER '
DB VERS/10+'0','.',VERS MOD 10+'0'
DB 0
ASKGET: DB 'SOURCE DRIVE NAME (OR RETURN TO SKIP): ',0
GETMSG: DB 'SOURCE ON '
GDISK: DS 1 ; FILLED IN AT GET FUNCTION
DB ':, THEN TYPE RETURN',0
ASKPUT: DB 'DESTINATION DRIVE NAME (OR RETURN TO REBOOT): ',0
PUTMSG: DB 'DESTINATION ON '
PDISK: DS 1 ; FILLED IN AT PUT FUNCTION
DB ':, THEN TYPE RETURN',0
ERRMSG: DB 'PERMANENT ERROR, TYPE RETURN TO IGNORE',0
DONE: DB 'FUNCTION COMPLETE',0
QDISK: DB 'INVALID DRIVE NAME (USE A-P)',0
NOFILE: DB 'NO SOURCE FILE ON DISK',0
BADFILE:
DB 'SOURCE FILE INCOMPLETE',0
SELMSG: DB 'DISK SELECTION ERROR',0
SYSMSG: DB 'NON-SYSTEM DISK ERROR',0
IOMSG: DB 'FATAL DISK I/O ERROR',0
SIGMSG: DB 'INVALID SYSTEM IMAGE (BAD SIGNATURE)',0
;
; VARIABLES
;
CBFTBL DW 0 ; ADDRESS OF CBIOS FUNCTION TABLE
IMGSIZ DB 0 ; IMAGE SIZE (COUNT OF 128 BYTE RECORDS)
;
RWFUN DB 0 ; ACTIVE READ/WRITE FUNCTION
RECCNT DB 0 ; ACTIVE REMAINING RECORDS TO READ/WRITE
BUFPTR DW 0 ; ACTIVE POINTER INTO BUFFER
;
ACTDSK DB 0 ; ACTIVE DISK NO
ACTTRK DW 0 ; ACTIVE TRACK
ACTSEC DW 0 ; ACTIVE SECTOR
ACTSPT DW 0 ; ACTIVE SECTORS PER TRACK
ACTFNC DW 0 ; ACTIVE FUNCTION (READ OR WRITE)
DS STKSIZE*2
STACK:
;
END