TITLE 'SYSGEN - SYSTEM GENERATION PROGRAM 8/79' ; ; COPYRIGHT (C) DIGITAL RESEARCH -- 1976, 1977, 1978, 1979 ; MODIFIED FOR MICRO-DECISION BY MORROW DESIGNS, INC. ; 09/03/82 ; .z80 aseg ;---------------------------------------------------------------------- ; Equates ;-------- ; VERS EQU 20 ;X.X NDISKS EQU 5 ;NUMBER OF DISK DRIVES SECSIZ EQU 128 ;SIZE OF EACH SECTOR LOG2SEC EQU 7 ;LOG 2 SECSIZ FCB EQU 005CH ;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 5H ;DOS ENTRY POINT BOOT EQU 0 ;JMP TO 'BOOT' TO REBOOT SYSTEM CONI EQU 1 ;CONSOLE INPUT FUNCTION CONO EQU 2 ;CONSOLE OUTPUT FUNCTION SELF EQU 14 ;SELECT DISK OPENF EQU 15 ;DISK OPEN FUNCTION DREADF EQU 20 ;DISK READ FUNCTION MAXTRY EQU 1 ;MAXIMUM NUMBER OF RETRIES ON EACH READ/WRITE CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED STACKSIZE EQU 16 ;SIZE OF LOCAL STACK WBOOT EQU 1 ;ADDRESS OF WARM BOOT (OTHER PATCH ENTRY ;POINTS ARE COMPUTED RELATIVE TO WBOOT) SELDSK EQU 24 ;WBOOT+24 FOR DISK SELECT SETTRK EQU 27 ;WBOOT+27 FOR SET TRACK FUNCTION SETSEC EQU 30 ;WBOOT+30 FOR SET SECTOR FUNCTION SETDMA EQU 33 ;WBOOT+33 FOR SET DMA ADDRESS READF EQU 36 ;WBOOT+36 FOR READ FUNCTION WRITF EQU 39 ;WBOOT+39 FOR WRITE FUNCTION sctcnt equ (LOADP-TPA)/SECSIZ ;---------------------------------------------------------------------- ; Begin the code Section ;----------------------- ; ORG TPA ;TRANSIENT PROGRAM AREA JP START DB 'COPYRIGHT (C) 1978, DIGITAL RESEARCH ' ;---------------------------------------------------------------------- ; TRANSLATE TABLE - SECTOR NUMBERS ARE TRANSLATED ; HERE TO DECREASE THE SYSGEN TIME FOR MISSED SECTORS ; WHEN SLOW CONTROLLERS ARE INVOLVED. TRANSLATION TAKES ; PLACE ACCORDING TO THE "SKEW" FACTOR SET ABOVE. ; OST: DB 0 SPT: DB 0 TRAN: DS 80,0 ; ; ; ;====================================================================== ; UTILITY SUBROUTINES ;==================== ; ;MULTIPLY THE SECTOR NUMBER IN A BY THE SECTOR SIZE ;-------------------------------------------------- ; MULTSEC: ld L,A ld H,0 ;SECTOR NUMBER IN HL add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl RET ;WITH HL = SECTOR * SECTOR SIZE ; READ CONSOLE CHARACTER TO REGISTER A ;------------------------------------- ; GETCHAR: ld C,CONI CALL BDOS CP 'A' OR 20H ;CONVERT TO UPPER CASE BEFORE RETURN Ret C ;RETURN IF BELOW LOWER CASE A CP ('Z' OR 20H) + 1 Ret NC ;RETURN IF ABOVE LOWER CASE Z and 5FH RET ; WRITE CHARACTER FROM A TO CONSOLE ;---------------------------------- ; PUTCHAR: ld E,A ld C,CONO CALL BDOS RET ;SEND CARRIAGE RETURN, LINE FEED ;------------------------------- CRLF: ld A,CR CALL PUTCHAR ld A,LF CALL PUTCHAR RET ; PRINT MESSAGE ADDRESSED BY H,L TIL ZERO WITH LEADING CRLF ;---------------------------------------------------------- ; CRMSG: PUSH Hl CALL CRLF POP Hl ;DROP THRU TO OUTMSG0 ; Output a message to the console ;-------------------------------- ; OUTMSG: ld A,(hl) OR A Ret Z PUSH Hl ;MESSAGE NOT YET COMPLETED CALL PUTCHAR POP Hl INc Hl JP OUTMSG ; SELECT DISK GIVEN BY REGISTER A ;-------------------------------- ; SEL: ld C,A ld hl,(wBOOT) ld De,SELDSK add hl,de ld E,0 jp (hl) ; SET UP TRACK ;------------- ; TRK: LD hl,(WBOOT) ;ADDRESS OF BOOT ENTRY ld De,SETTRK ;OFFSET FOR SETTRK ENTRY add hl,de jp (hl) ;GONE TO SETTRK ; SET UP SECTOR NUMBER ;--------------------- ; SEC: LD hl,(WBOOT) Ld De,SETSEC add hl,de jp (hl) ; SET DMA ADDRESS TO VALUE OF B,C ;-------------------------------- ; DMA: Ld hl,(WBOOT) ld De,SETDMA add hl,De jp (hl) ; PERFORM READ OPERATION ;----------------------- ; READ: Ld hl,(WBOOT) Ld De,READF add hl,De jp (hl) ; PERFORM WRITE OPERATON ;----------------------- ; WRITE: ld C,2 WRTD: ld hl,(WBOOT) ld De,WRITF add hl,De jp (hl) ; DISK READ FUNCTION ;------------------- ; DREAD: ld C,DREADF JP BDOS ; FILE OPEN FUNCTION ;------------------- ; OPEN: ld C,OPENF JP BDOS ; GET OR PUT CP/M (RW=0 FOR READ, 1 FOR WRITE) DISK IS ALREADY SELECTED ;---------------------------------------------------------------------- ; GETPUT: ld Hl,LOADP ;LOAD POINT IN RAM FOR CP/M DURING SYSGEN ld (DMADDR),hl ;CLEAR TRACK TO 00 ld A,-1 ;START WITH TRACK EQUAL -1 ld (TRACK),a ; READ OR WRITE NEXT TRACK ;------------------------- ; RWTRK: ld Hl,TRACK inc (hl) ;TRACK = TRACK + 1 LD a,(OST) ;NUMBER OF OPERATING SYSTEM TRACKS CP (hl) ;= TRACK NUMBER ? Jp Z,ENDRW ;END OF READ OR WRITE ; oTHERWISE NOTDONE, GO TO NEXT TRACK ld C,(hl) ;TRACK NUMBER ld B,0 CALL TRK ;TO SET TRACK ld A,-1 ;COUNTS 0, 1, 2, . . . 25 ld (SECTOR),a ;SECTOR INCREMENTED BEFORE READ OR WRITE ; READ OR WRITE SECTOR ;--------------------- ; RWSEC: ld a,(SPT) ;SECTORS PER TRACK ld Hl,SECTOR inc (hl) ;TO NEXT SECTOR CP (hl) ;A=26 AND M=0 1 2...25 (USUALLY) Jp Z,ENDTRK ; READ OR WRITE SECTOR TO OR FROM CURRENT DMA ADDR Ld Hl,SECTOR ld E,(hl) ;SECTOR NUMBER ld D,0 ;TO DE ld Hl,TRAN ld B,(hl) ;TRAN(0) IN B add hl,De ;SECTOR TRANSLATED ld C,(hl) ;VALUE TO C READY FOR SELECT PUSH Bc ;SAVE TRAN(0),TRAN(SECTOR) ld B,0 CALL SEC ;SET UP SECTOR NUMBER POP Bc ;RECALL TRAN(0),TRAN(SECTOR) ld A,C ;TRAN(SECTOR) SuB B ;-TRAN(0) CALL MULTSEC ;*SECTOR SIZE ex de,hl ;TO DE ld hl,(DMADDR) ;BASE DMA ADDRESS FOR THIS TRACK add hl,De ;+(TRAN(SECTOR)-TRAN(0))*SECSIZ ld B,H ld C,L ;TO BC FOR SEC CALL CALL DMA ;DMA ADDRESS SET FROM B,C ; DMA ADDRESS SET, CLEAR RETRY COUNT xor A ld (RETRY),a ;SET TO ZERO RETRIES TRYSEC: LD a,(RETRY) ;TRY TO READ OR WRITE CURRENT SECTOR CP MAXTRY ;TOO MANY RETRIES? Jp C,TRYOK ; PAST MAXTRIES, MESSAGE AND IGNORE Ld Hl,ERRMSG CALL OUTMSG CALL GETCHAR CP CR Jp NZ,REBOOT ; TYPED A CR, OK TO IGNORE CALL CRLF JP RWSEC TRYOK: INc A ;OK TO TRY READ OR WRITE ld (Retry),a ;&&& LD a,(RW) ;READ OR WRITE? OR A Jp Z,TRYREAD CALL WRITE ;MUST BE WRITE JP CHKRW ;CHECK FOR ERROR RETURNS TRYREAD:CALL READ CHKRW: OR A Jp Z,RWSEC ;ZERO FLAG IF R/W OK JP 0 ;ERROR, WARM BOOT ; END OF TRACK ENDTRK: LD a,(SPT) ;SECTORS PER TRACK CALL MULTSEC ;*SECSIZ ex de,hl ;TO DE Ld hl,(DMADDR) ;BASE DMA FOR THIS TRACK add hl,de ;+SPT*SECSIZ ld (DMADDR),hl ;READY FOR NEXT TRACK JP RWTRK ;FOR ANOTHER TRACK ;END OF READ OR WRITE, RETURN TO CALLER ENDRW: LD a,(RW) ;SEE IF READ OR A Ret Z ;RETURN IF READ ld C,1 ;DO LAST WRITE AGAIN, CALL WRTD ;BUT FORCE WRITE OF LAST sector OR A ;CHECK FOR ERROR Ret Z ;RETURN IF NO ERROR ld Hl,ERRMSG ;PRINT ERROR MESG. CALL OUTMSG CALL GETCHAR ;GET INPUT CP CR ;SEE IF CR Jp NZ,REBOOT ;REBOOT CALL CRLF ;IGNORE RET RET START: ld SP,STACK ;SET LOCAL STACK POINTER ld Hl,SIGNON CALL OUTMSG ;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,sctcnt ;PRE-READ FILE PRERD: 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 DMA ;DMA ADDRESS SET 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 ;EOF ENCOUNTERED IN INPUT FILE ;----------------------------- ; BADRD: Ld Hl,BADFILE CALL CRMSG JP REBOOT GETSYS: 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 CALL BADDISK ;INVALID DRIVE NUMBER JP GETSYS ;TO TRY AGAIN ; SELECT DISK GIVEN BY REGISTER A ;-------------------------------- ; GETC: ADd a,'A' ld (GDISK),a ;TO SET MESSAGE SUb 'A' PUSH af ; 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 POP af CALL SEL ;TO SELECT THE DRIVE CALL FIXSKW Xor A ld (RW),a CALL GETPUT Ld Hl,DONE CALL OUTMSG ; PUT SYSTEM ;----------- ; PUTSYS: Ld Hl,ASKPUT CALL CRMSG CALL GETCHAR CP CR Jp Z,REBOOT SUb 'A' CP NDISKS Jp C,PUTC CALL BADDISK ; INVALID DRIVE NAME JP PUTSYS ;TO TRY AGAIN ;SET DISK FROM REGISTER C PUTC: ADd a,'A' ld (PDISK),a ;MESSAGE SET SUb 'A' PUSH af ; PUT SYSTEM, SET RW TO WRITE Ld Hl,PUTMSG CALL CRMSG CALL GETCHAR CP CR Jp NZ,REBOOT CALL CRLF POP af CALL SEL ;SELECT DEST DRIVE CALL FIXSKW Ld Hl,RW ld (hl),1 CALL GETPUT ;TO PUT SYSTEM BACK ON DISKETTE ld Hl,DONE CALL OUTMSG JP PUTSYS ;FOR ANOTHER PUT OPERATION REBOOT: ld A,0 CALL SEL CALL CRLF JP BOOT ; BAD DISK NAME ;-------------- ; BADDISK: Ld Hl,QDISK CALL CRMSG RET ERR: Ld Hl,SERR CALL CRMSG JP REBOOT NOMTCH: OR A ;SEE IF SYSTEM S OR D SIDED Ld Hl,SMESG ;GET SINGLE SIDED MESG. Jp Z,SING ;JMP IF SINGLE Ld Hl,DMESG ;DOUBLE SIDED MESG SING: CALL CRMSG JP PUTSYS FIXSKW: Ld De,0AH ;OFFSET TO DPB POINTER add hl,de ;ADD TO DPH POINTER ld E,(hl) ;GET DPB POINTER INc Hl ld D,(hl) ex de,hl ld A,(hl) ;GET SECTORS/TRACK ld (SPT),a ;SAVE PUSH af ld De,13 ;OFFSET TO RESERVED TRACKS add hl,De ld A,(hl) ;RESERVED TRACKS ld (OST),a ;SAVE POP af ;SECTORS/TRACK ld E,A INc E RRCa ;DIVIDE BY 8 RRCa RRCa ld D,A ld C,1 ;FIRST SECTOR Ld Hl,TRAN ;POINTER TO TABLE TRLP0: ld B,8 ;LOGICAL SECTORS/PHYSICAL SECTOR TRLP1: ld (hl),C ;STORE SECTOR IN TABLE INc C ;INCREMENT SECTOR INc Hl ;INCREMENT POINTER DJNZ TRLP1 ;LOOP Dec D ;SEE IF DONE Ret Z ;RETURN IF DONE ld A,8 ;SKEW ADD a,C ;ADD TO SECTOR ld C,A CP E ;SEE IF OVERFLOW JR C,TRLP0 ;LOOP IF NO OVERFLOW ld C,9 JR TRLP0 ;---------------------------------------------------------------------- ; DATA AREAS ;----------- ; MESSAGES SIGNON: DB 'SYSGEN VER ' DB VERS/10+'0','.',VERS MOD 10+'0',' MD2.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, B, C, D, OR E)',0 NOFILE: DB 'NO SOURCE FILE ON DISK',0 BADFILE: DB 'SOURCE FILE INCOMPLETE',0 SERR: DB 'WRONG VERSION OF CP/M',0 SMESG: DB 'SINGLE SIDED DISKETTE CANNOT ACCEPT DOUBLE SIDED SYSTEM',0AH,0 DMESG: DB 'DOUBLE SIDED DISKETTE CANNOT ACCEPT SINGLE SIDED SYSTEM',0AH,0 ; VARIABLES ;---------- ; SDISK: DS 1 ;SELECTED DISK FOR CURRENT OPERATION TRACK: DS 1 ;CURRENT TRACK SECTOR: DS 1 ;CURRENT SECTOR RW: DS 1 ;READ IF 0, WRITE IF 1 DMADDR: DS 2 ;CURRENT DMA ADDRESS RETRY: DS 1 ;NUMBER OF TRIES ON THIS SECTOR DS STACKSIZE*2 STACK: END