TITL PTDOS 2.00 PAGE ASCF 0 NO EXTENDED ASCII IFLS . LIST THE IF'S TOO * * * * * * * * * PTDOS v2.00 * * FLOPPY DISK OPERATING SYSTEM * * * * COPYRIGHT 1978 BY: * * PROCESSOR TECHNOLOGY CORP. * 7100 JOHNSON INDUSTRIAL DRIVE * PLEASANTON, CALIF 94566 * * << ALL RIGHTS RESERVED >> * * * DESIGNED AND WRITTEN BY: PHILIP LEVY * *********************************************************** PAGE * * * * THE FOLLOWING DEFINE THE SYSTEM CONFIGURATION * * * * CONFIGURATION PARAMETERS * ********************* * * SYSTEM OPERATIONS * CREOP EQU 0 CREATE FILE OPEOP EQU 1 OPEN FILE KILOP EQU 2 DELETE FILE RBLOP EQU 3 READ BLOCK WBLOP EQU 4 WRITE BLOCK SPAOP EQU 5 SPACE EOFOP EQU 6 ENDFILE CLOOP EQU 7 CLOSE FILE CHTOP EQU 8 CHANGE TYPE CHAOP EQU 9 CHANGE ATTRIBUTES CHNOP EQU 10 CHANGE NAME INFOP EQU 11 INFORMATION REQUEST SUNOP EQU 12 SET DISK UNIT RETOP EQU 13 RETURN TO CI RESOP EQU 14 RESET, THEN RETURN TO CI ABTOP EQU 15 ABORT, THEN RETURN TO CI SEKOP EQU 16 SEEK OPERATION RNDOP EQU 17 RANDOMIZE CAOP EQU 18 CLOSE ALL/UNIT CTLOP EQU 19 FILE CONTROL/STATUS SREST EQU 20 SHORT RESET TO CI DRDOP EQU 21 DELIMITED READ DWROP EQU 22 DELIMITED WRITE DSPOP EQU 23 DELIMITED SPACE OPERATION RTROP EQU 24 RETURN WITH TRAP OPERAITON * MAXOP EQU RTROP MAX OPERATION * * ********************* * * ERROR NUMBERS * * * THESE ARE THE CORRECT ERROR NUMBERS * ERNEX EQU 1 NONEXISTENT FILE ERAEX EQU ERNEX+1 FILE ALREADY EXISTS ERUFN EQU ERAEX+1 UNASSIGNED FILE NUMBER ERPRO EQU ERUFN+1 PROTECTION VIOLATION ERNIF EQU ERPRO+1 FILE NOT TYPE IMAGE ERMOP EQU ERNIF+1 ILLEGAL OPERATION ON MUDTIPLY OPEN FILE ERRAC EQU ERMOP+1 RANDOM ACCESS TO NON-RANDON FILE ERRDV EQU ERRAC+1 RANDOM ACCESS TO DEVICE FILE ERZBC EQU ERRDV+1 EMPTY DEVICE FILE * ERIOP EQU ERZBC+1 ILLEGAL PTDOS OPERATION ERIBF EQU ERIOP+1 ILLEGAL BUFFER ADDRESS ERIBS EQU ERIBF+1 ILLEGAL BLOCK SIZE ERINM EQU ERIBS+1 ILLEGAL CHARACTER IN NAME ERICU EQU ERINM+1 ILLEGAL CHARACTER IN UNIT ERIUN EQU ERICU+1 ILLEGAL UNIT ERNTL EQU ERIUN+1 NAME TOO LONG ERMEM EQU ERNTL+1 USER MEMORY PROTECT VIOLATION ERSMP EQU ERMEM+1 SYSTEM MEMORY PROTECT VIOLATION ERUCN EQU ERSMP+1 UNIT CONFLICT ERIUP EQU ERUCN+1 ILLEGAL UTILITY OPERATION ERDRI EQU ERIUP+1 DRIVER ERROR ERIDA EQU ERDRI+1 ILLEGAL DRIVER ACCESS ERNCT EQU ERIDA+1 DRIVER NOT PARTICIPATING IN THIS CTRL * OPERATION * EREOF EQU 24 END OF FILE ENCOUNTERED (OR BOF) ERSEK EQU EREOF+1 SEEK ADDRESS OUT OF RANGE * ERTOP EQU ERSEK+1 TOO MANY FILES OPEN ERMOV EQU ERTOP+1 MEMORY OVERFLOW ERNID EQU ERMOV+1 NO FILE ID'S LEFT ERDFL EQU ERNID+1 DISK FULL ERDIR EQU ERDFL+1 DIRECTORY FULL ERBLF EQU ERDIR+1 BAD LOAD FILE * * ERFSB EQU 32 FILE STRUCTURE BAD ERFIC EQU ERFSB+1 FILE ID CONFLICT ERBSC EQU ERFIC+1 BLOCK SIZE CONFLICT ERSCC EQU ERBSC+1 SECTOR CONFLICT ERCFS EQU ERSCC+1 CAN'T FIND SECTOR ERCRC EQU ERCFS+1 CRC ERROR OR READ/WRITE ABORTS ERCFT EQU ERCRC+1 CAN'T FIND TRACK ERRBC EQU ERCFT+1 READ-BACK-CHECK FAILED ERLOK EQU ERRBC+1 DISK IS WRITE LOCKED ERXXX EQU ERLOK+1 CATESTROPHIC ERROR * * ERRED EQU 39H DRIVE NOT READY * ** * THESE ARE THE OLD SYMBOLS,WHICH ARE STILL USED HERE * SERR0 EQU ERRAC - FILE NOT INDEXED SERR2 EQU ERSEK - SEEK ADDR OUT OF RANGE RERR0 EQU ERRDV - RANDOM OP ON DEVICE FILE * CER0 EQU ERAEX - FILE ALREADY EXISTS CER1 EQU ERDIR - DIRECTORY FULL DER0 EQU ERNEX - NONEXISTENT FILE DER1 EQU ERMOP - ATTEMPT TO KILL OR EOF MULTIPLY OPEN FILE OER1 EQU ERIBF - ILLEGAL BUFFER ADDRESS PER0 EQU ERPRO - PROTECT VIOLATION EER0 EQU EREOF - END OF FILE FINE0 EQU ERNEX - FILE DOES NOT EXIST FINE1 EQU ERPRO - PROTECTION FER0 EQU ERTOP - NO FCBS AVAILABLE MER0 EQU ERMOV - MEMORY OVERFLOW PER1 EQU ERUFN - ILLEGAL FCB IER0 EQU ERNID - NO IDS LEFT FBER EQU ERFSB - FS BAD CHER EQU ERPRO - ALTERATION PROTECTED CIER0 EQU ERBLF - BAD LOAD FILE CIER1 EQU ERNIF - NOT IMAGE FILE * * DAER0 EQU ERDFL - DISC IS FULL DAER1 EQU ERIBS - ILLEGAL BLOCK SIZE DVER0 EQU ERDRI - DRIVER ERROR IDAER EQU ERIDA - ILLEGAL DRIVER ACCESS ILOER EQU ERIOP - ILLEGAL OPERATION UNER0 EQU ERIUN - ILLEGAL UNIT LDE2 EQU ERZBC - BAD DRIVER--ZERO UTE0 EQU ERIUP - BAD UTILITY OPERATION * MPE0 EQU ERMEM - MEMORY PROTECT MPE1 EQU ERSMP - SYSTEM MEMORY PROTECT CHR2 EQU ERUCN - UNIT CONFLICT ICE0 EQU ERINM - ILLEGAL CHARACTER IN NAME ICE1 EQU ERICU - ILLEGAL CHARACTER IN UNIT CSER0 EQU ERXXX - CATESTROPHIC ERROR * * ********************* * * DRIVER TYPE/STATUS BITS * SBDUP EQU 128 DUPLICATIVE SBIAT EQU 64 INTERACTIVE SBTAB EQU 32 TABBING SBSTB EQU 16 SET TABS SBFF EQU 8 FORM-FEED SBATB EQU 4 ABSOLUTE TABS SBINT EQU 2 INTERRUPT DRIVEN SBPRO EQU 1 SETTABLE PROMPT * ********************* * * SECONDARY OPERATIONS * UXOP EQU 0 EXPLAIN ERROR NICELY UXOP1 EQU 1 SECOND LEVEL * CCLDE EQU 32 LOADER OPERATION CODE * * ********************* * * * * SYSTEM FILE INFORMATION * * * DIRECTORY INFORMATION * IDDIR EQU 2 DIRECTORY FILE ID DIRDB EQU 200 FIRST BLOCK OF DISK DIRECTORY * NMLEN EQU 8 NAME LENGTH DREMS EQU 24 MAX ENTRIES PER SECTOR DICNT EQU 8 NUMBER OF DIRECTORY SECTORS * * * SYSTEM GLOBAL FILE * DASPB EQU 6 FIRST BLOCK OF SYSTEM GLOBAL IDSPA EQU 5 FILE ID * * * SYSTEM RESIDENT * DAREB EQU 8 FIRST SECTOR OF RESIDENT IDRES EQU 4 FILE ID D2REB EQU 16 SECOND SECTION OF RESIDENT * * * FSM (FREE SPACE MAP) INFORMATION * IDFSM EQU 1 FSM FILE ID DAFSB EQU 208 BLOCK # OF FSM (TRACK 26) * * * NEXT FILE ID FILE INFORMATION * IDNID EQU 3 NEXT ID FILE ID DANIB EQU 209 BLOCK OF NEXT ID FILE NIDBC EQU 2 BYTE COUNT OF BLOCK * * * BOOTSTRAP FILE * DABOS EQU 0 ST ADDR OF DISK BLOCK # ( must never change) IDBOT EQU 6 FILE ID * ********************* * * HEADER VALUES ETC * * * SECTOR SIZES * SECTSZ EQU 500 FULSZ EQU 512 # DATA BYTES IN FOLLOWING BLOCKS * * * FILE STRUCTURE LINKAGE VALUES * BOFCD EQU 65535 BOF CODE IN BACK POINTER EOFCD EQU 32768 EOF BIT IN FORE POINTER * * * FILE PROTECTION ATTRIBUTE BITS * PDEL EQU 1 DELETE PROTECT PWRI EQU 2 WRITE PROTECT PREA EQU 4 READ PROTECT PFINF EQU 8 INFORMATION PROTECT PATR EQU 16 ATTRIBUTE CHANGE PROTECT PNAT EQU 32 NAME AND TYPE CHANGE PROTECT PALO EQU 64 ALLOCATION PROTECTION * * * DEFINE FILE TYPES * SYSIM EQU 00H SYSTEM IMAGE TYPE --(I00) BNTYP EQU 80H BINARY DATA FILE --(00) UTTYP EQU 01H UTILITY TYPE * IMTYPE EQU 80H IMAGE FILE MASK (OFF IS IMAGE!!) * * ******************************************* * * * DRIVER TABLE STRUCTURE * * THESE ARE DISPLACEMENTS INTO A DRIVER * DTRB EQU 0 READ BLOCK DTRNB EQU 2 READ NEXT BLOCK DTRLB EQU 4 READ LAST BLOCK DTWBR EQU 6 WRITE BLOCK: LOAD NEXT DTWB EQU 8 WRITE BLOCK DTREW EQU 10 REWIND DTEOF EQU 12 END-FILE DTCLO EQU 14 CLOSE DTSEK EQU 16 SEEK DTCTL EQU 18 CONTROL/STATUS DTBLK EQU 20 BLOCK SIZE DTITO EQU 22 IMMEDIATE TRANSFER OPTION DTINI EQU 23 INITIALIZE ENTRY POINT * PAGE * * ******************************************* * * * SYSTEM GLOBAL AREA STUFF * * * MEMORY AREA * MINMA EQU 08800H LOWEST MEMORY ADDRESS LNMBF EQU 0FB8H LENGTH OF MAIN BUFFER AREA (4024) FCB0 EQU MINMA+LNMBF START OF FCB AREA XFER EQU 0F016H DISK ROUTINE * * * FILE CONTROL BLOCKS * MAXFCB EQU 8 MAX. NUMBER OF OPEN FILES MINFCB EQU 5 MIN. NUMBER OF FILE CONTROL BLOCKS LNFCB EQU 34 LENGTH OF FCB. MUST AGREE WITH LAYOUT !!!!!! FCBLN EQU LNFCB*MAXFCB LENGTH OF FCB AREA * * FCB SIZE DEFINED LITERALLY <<-------------< WARNING * * * DEFINE SYSTEM STACK * BOTSK EQU FCB0+FCBLN MAX TOP OF STACK ADDRESS STKSZ EQU 60 STACK SIZE TOPSK EQU BOTSK+STKSZ BOTTOM OF STACK (INITIAL TOP) * * INITIAL ELEMENTS IN THE STACK ALWAYS LOOK LIKE THIS * UHL EQU TOPSK-2 USER HL UL EQU UHL USER L UH EQU UHL+1 USER H UD EQU TOPSK-3 USER D UE EQU TOPSK-4 USER E UDE EQU UE UB EQU TOPSK-5 USER B UC EQU TOPSK-6 USER C UBC EQU UC UA EQU TOPSK-7 USER A UPSW EQU TOPSK-8 USER PSW UTOS EQU TOPSK-10 USER SP * PAGE * * ******************************************* * * * * * * SYSTEM GLOBAL AREA * ORG TOPSK * SGAREA EQU $ BEGINNING OF THE SYSTEM GLOBAL AREA SP1 EQU -MINFCB*LNFCB+SGAREA LOAD ADDRESS FOR SYSGLOBL MASPA EQU SP1 SAME * * * * THE FOLLOWING PARAMETERS ARE AVAILABLE TO THE USER * THROUGH THE POINTER IN THE ENTRY POINT AREA. * * * DEFAULT FILE NUMBERS * CIFILE DB 0 C/I INPUT FILE COFILE DB 1 C/I OUTPUT FILE UTIL DB 2 DEFAULT UTILITY FILE =2 ECFILE DB 1 ECHO OUTPUT FILE * * DO NOT CHANGE THE ORDER OR POSITION OF THE ABOVE FOUR * PARAMETERS UNDER ANY CIRCUMSTANCES!!!! * DUNIT DB 0 DEFAULT DISK DRIVE AND UNIT SYSFIL DB 3 NUMBER OF SYSTEM FILES CONFIGURED MAXUN DB 2 NUMBER OF DRIVES+1 CONFIGURED * SWITCHS DB 0 BITS FOR ON OFF DB 0 USER SENSE SWITCHES * * * ERROR HANDLING * EERR DW -1 EOF-BOF ERRORS AERR DW 0 ABORTIVE ERRORS FERR DW 0 FATAL, SERIOUS ERRORS * * * MISC. * CRTRAP DW -1 C/I TRAP RETURN UPROT DW 0 USER MEMORY PROTECT * STFLG DB 0 EXTRA CHARACTER WAITING ON CONIN FLAG INBYT DB 0 THE SAID EXTRA CHARACTER * * CI READ/WRITE/TEST POINTERS * RCH DW CIRCH READ CONSOLE WCH DW CIVDM WRITE CONSOLE SCH DW CITCH TEST CONSOLE * NULLS DB 0 NUMBER OF NULLS TO FOLLOW CR * * * * CONFIGURATION INFORMATION * * SYSTEM VERSION * DB 52H SYS VERSION 2.0.2 DB 01H MONTH MM DB 01H DATE DD DB 88H YEAR YY * ASC 'PTDOS2.0' DISK NAME * ASC 'PTDOS' PASSWORD DW 0 (8 CHARS, ZERO FILL) DB 0 * * * INTERRUPT STUFF * BDSK1 DW -1 STANDARD RETURN INTERRUPT ADDRESS BDSK2 DW -1 FAST " " " " " " IFLG1 DB 0 FLAG TO RE-ENABLE INTERRUPTS IFLG2 DB 0 DISK DONE FLAG FOR INT HANDLER * * * MEMORY CONFIGURATION * LOWAD DW MINMA MINIMUM AVAILABLE LOCATION * * * SYSTEM SWITCH FLAGS * SWECH DB 0 ECHO ENABLE SWLOK DB 0 DISK WRITE LOCK SWUPS DB 0 UPSHIFT ASCII SWRBC DB 0 DISK READ-BACK-CHECK AFTER WRITE SWBIO DB 0 BINARY I/O ON CONSOLE SWLOG DB 0 LOG FILE FOR CI ECHO FLAG SWVRB DB 1 VERBOSE DISABLE SWFTR DB 0 FUTURE (I.E. ISN'T 8 A NICE NUMBER) * * * LEAVE SOME ROOM FOR FUTURE JUNK * GLVDC DW PCRCK SET SCREEN LINE ADDRESS DW -1 * PAGE * * * * * * ///// THE PARAMETERS BELOW ARE DEFINED FOR SYSTEM //// * ///// USE FROM SYSGLO. DO NOT CHANGE THEIR LOCATION /// * * * FCB AREA PARAMETERS * HIGHA DW MAXFCB*LNFCB+FCB0 TOP AVAILABLE LOCATION MINAD DW FCB0-BUFT-BUFT2 MINIMUM BUFFER ALLOCATED SO FAR FCBASE DW FCB0 FIRST FCB ADDRESS NFCB DB MAXFCB NUMBER OF FCBS * CRSEEN DB 0 CR FLAG FOR TTY DRIVER TDPRO DW CIMSG CI TTY PROMPT MESSAGE POINTER FRADD DW 0 FCB RESTORATION ADDRESS * * * * PAGE * * ******************************************* * * * < PARAMETER CONVERTER > * ASCII: - BINARY * * VERSION 1.1 OCT. 25, 1976 S. DOMPIER * * CALLING SEQUENCE: * reg HL has ASCII value string address * terminated by a binary zero. * * PCONA: reg B has alpha base chr * PCONB: reg B has binary base * * max parameter values: FFFF<:H> 65535:D * 1111 1111 1111 1111:B 177777:Q * * alpha base notation: B = binary * O = octal * Q = octal * D = decimal * H = hexidecimal * * PCONA LXI D,PBTBL-1 base table XCHG MVI C,6 table entry count+1 MOV A,B get base chr * CBASE DCR C JZ ZRET illegal base chr INX H CMP M INX H point to next base chr/value JNZ CBASE MOV B,M get binary base value XCHG * * convert base-n digits to binary * PCONB MOV A,B get base STA PBASE save base PUSH H save input buffer address LXI D,0 initialize total * CNUM2 LDA PBASE get base MOV B,A POP H MOV A,M get chr ORA A binary zero? RZ . yes, we are done * INX H PUSH H save CBUF pointer SUI 30H strip ascii bias CPI 10 >10? JC CNUM3 ANI 0DFH upshift, if necessary SUI 7 strip alpha bias CPI 10H illegal chr? > "F" JNC ZRET CPI 10 JC ZRET * CNUM3 MOV C,A save number SUB B subtract base JP ZRET not legal in base LXI H,0 clear temp total CALL MULT total * base MVI B,1 one pass MVI D,0 MOV E,C CALL MULT add digit XCHG JMP CNUM2 get next digit * * * multilpy DE*B * MULT INR B MULT2 DCR B RZ . done ~.~.~.~.~.~ EXIT ~.~.~.~.~ DAD D JNC MULT2 continue if no overflow JMP ZRET > 64K error * * * alpha base table * PBTBL DW 242H 'B' binary DW 84FH 'O' octal DW 851H 'Q' octal DW 0A44H 'D' decimal DW 1048H 'H' hexidecimal * * MAXIN EQU 20 maximum chr input count * * * THIS IS THE REST OF PSCAN FROM PAGE "B" UP TOP * * error returns * ERRET CALL PREAD set-up error return address ZRET XRA A zero reg A = field error ERET STC . set carry = error MOV E,A error number to reg E JMP PNR2 * * PREAD CPI 0D5H ascii in HL from base in B? LHLD UIBUF -> USER INPUT JNZ PR2 nope CALL PCONB convert value; returns DE JMP PNR1 normal return * * PR2 ANI 20H one chr only? JZ R1 no CALL G1 get one chr from CI or user buffer STA LC JMP PNR1 go home * * * read chrs into OUBUF * R1 MVI C,0 LHLD UOBUF R2 CALL GETCH get chr JZ STOP done, found delimiter ,/;/cr MOV M,A store chr in UOBUF INX H INR C update chr count MVI A,MAXIN maximum input count SUB C RZ . to many chrs JMP R2 get next chr * * * get input character * RETURN IN A, ZERO IF DELIMITER * GETCH PUSH H save output pointer GETC2 CALL G1 CPI ' ' skip spaces JZ GETC2 MOV L,A SAVE CHR IN L LDA OPT ANI 88H ADD A SET CARRY AND ZERO FLAGS FOR JUMPS BELOW MOV A,L RESTOR CHR POP H JNZ DLTEST SKIP ALL BUT NORMAL DELIMITERS JC DLMTST VALUE OP, SKIP NO DELIMITERS JMP DLTST NAME OP, SKIP ALL BUT NAME DELIMITERS * * G1 LDA OPT ANI 40H user input buffer? JNZ G2 yes LDA CIFILE get cifile number from DOS PUSH B CALL RB read one byte from cifile JMP ERET POP B RET * * G2 LHLD UIBUF get user input buffer pointer MOV A,M INX H SHLD UIBUF RET * * STOP MVI M,0 set stop byte (last UOBUF chr), MOV L,C stops scan in PCON or puts 0 MOV H,A after name SHLD CCLC save chr count and last chr scanned MOV A,C ORA A any characters? JZ PNRET nope, its a default field LHLD UOBUF get name/scratch buffer pointer LDA OPT get options MOV B,A ANI 8 CHECK IF READ ALL CHRS TO NORMAL, JNZ PNRET RETURN CHR - , ; cr 0 MOV A,B RAL . name? JNC NAME * * VALUE FIELD * DCX H MVI B,'H' set hexidecimal base default * V2 INX H MOV A,M ORA A JZ V3 if binary zero, field is finished SUI ':' base? JNZ V2 no, look for ':' or binary zero MOV M,A set binary zero in place of ':' INX H MOV B,M get base chr INX H CMP M better be zero! RNZ . error, only one base chr allowed. * V3 LHLD UOBUF point to value string CALL PCONA convert ascii string to binary POP H RET . normal return, value in DE * * * NAME FIELD * NAME LDA LC GET LAST CHR SCANNED CALL DLTEST CHECK IF , ; cr 0 MVI A,-1 REG E = -1 ON RETURN, JNZ NOPEN FILE NOT CREATED OR OPENED * MOV A,M GET FIRST NAME CHR CPI '#' file number? LXI B,0A00H SET C=0 & BINARY BASE = 10 JNZ N1 NOPE INX H CALL PCONB CONVERT FILE NUMBER TO BINARY POP H CLEAR STACK FOR NORMAL RETURN RET * * N1 LDA OPT GET OPTIONS ORA C ADD IN POSSIBLE SUPPRESS CREATE FROM OPEN RAR . suppress create? LHLD UOBUF POINT TO NAME JC POPEN yes LXI D,-4 POINT TO TYPE (CREATE BLOCK) DAD D XCHG CALL SYS DB CREOP create file JMP CREER something wrong CRNR MVI C,1 set suppress create JMP N1 now attempt to open file * * CREER CPI ERAEX existing file? JNZ ERET no, something else wrong LDA OPT get options ANI 2 . force create? JZ CRNR no, open file MVI A,ERAEX yes; and, JMP ERET set existing file error. * * * OPEN, DE HAS UOBUF WITH NAME * POPEN LXI D,0 clear value/ set static buffer RAR . suppress open? RAR JC PNRET yes, return XCHG . name pointer to DE, CALL SYS static buffer to HL. DB OPEOP open named file JMP ERET opps! * * NOPEN MOV E,A save file number OR -1 MVI D,0 clear reg D POP H return, with file number in E RET * * * * * LAST WORD LOADED * DB 0 THIS BYTE IT A SPARE * SP2 EQU $-1 LNSPA EQU SP2-SP1+1 LENGTH OF SYSGLOBL (DO NOT CHANGE) * * *** WARNING, MAX = 380H (ELSE MOVE SYS GLO AREA) *** * * PAGE * * ******************************************* * * * * TEMPORARY STORAGE AREA * * OPER RES 1 DOS OPERATION * * DIRECTORY SEARCH PARAMETERS * DFC RES 2 FREE DIRECTORY ENTRY ADDRESS DBUF RES 2 DIRECTORY ENTRY POINTER DCNT RES 1 DIRECTORY ENTRY COUNTER DRID RES 2 FILE ID TO SEARCH FOR * TBUFA RES 2 TRUE BUFFER ADDRESS (USED ALL OVER) * DISA RES 2 DISPATCH ADDRESS (SYS) * AFBT1 RES 1 BLOCKS REQUIRED AFBT3 RES 2 TRACK MAP POINTER AFBT4 RES 2 START SECTOR (BLOCK#) AFBT6 RES 2 PBUF POINTER * DABT1 RES 2 BUFFER ADDRESS DABT2 RES 2 BUFFER SIZE DABT3 RES 1 FCB COUNTER * * WBUFSZ RES 2 AUTO DEALLOCATION WBUFAD RES 2 * SFCT1 RES 1 COUNT FOUND SFCT2 RES 1 FCB COUNTER * LNKT1 RES 2 CURRENT BLOCK # LNKT2 RES 2 BACK POINTER * * SOU RES 2 SOURCE (RWP) DEST RES 2 DESTINATION RWF RES 1 READ/WRITE FLAG LCNT RES 2 LOCAL COUNT DELFG RES 1 DELIMITER FLAG (0=>NONE,-1=>SEARCHING,1=>FND) * ETMP RES 2 FOR EOF ECRS RES 2 LAST BLOCK CLCNT EQU SOU CLOSE ALL FCB COUNTER RINAD RES 2 RANDOM INDEX ADDRESS (IN MEMORY) * LSECT RES 2 LAST BLOCK ADDRESS (DDRNB) * RFBCN RES 1 COUNT, (RFBLK) RFBC1 RES 1 COUNT, (RFBLK) * * XA RES 1 A FOR UTIL AND CI XHL RES 2 HL FOR UTIL XOPER RES 1 OPER FOR UTIL * RNPTR RES 2 RANDOM INDEX POINTER RNCNT RES 1 ENTRY COUNT CICNT RES 1 COUNTER (CI) CPNT RES 2 POINTER (CI) CECT EQU CPNT ECHO COUNT (CI) CERC EQU CICNT LINE POSITION (CI) FRAD2 RES 2 FOR OPEN XQFLG RES 1 EXECUTE FLAG FOR CI CONCH RES 1 CHARACTER READ BY CONIN OR CONOUT * * * PSCAN TEMPORARIES * PBASE DS 1 BASE CHARACTER OPT DS 1 OPTIONS UOBUF DS 2 USER OUTPUT BUFFER POINTER UIBUF DS 2 USER INPUT BUFFER POINTER CCLC EQU $ CHAR CT/LAST CHAR CC DS 1 CHARACTER COUNT LC DS 1 LAST CHARACTER ERSWC DS 2 AERR SAVE AREA RSTK DS 2 RETURN ADDRESS * * * VDM TEMPORARIES * SPEED RES 1 VDMAD RES 2 BOT RES 1 KNTT RES 1 * * DISK DRIVER TEMPORARIES USED IN RDSK,WDSK(H) * * INTRT DS 2 FOR INTERRUPT PROCESSING RETURN INRET DS 2 INTERRUPT TEST ROUTINE ADDRESS DSKRT DS 2 SYSTEM STACK SAVE LOCATION DRVRT DS 2 DRIVER STACK SAVE LOCATION DSKRD DS 2 DRIVE NOT READY RETURN TRAP * PAGE * * ******************************************* * * * * SYSTEM BUFFERS * * * * DISK ALLOCATION BUFFER DKBUF RES 80 TRACKS/DISK ( 1 BIT/BLOCK) * * NOTE: OUTPUT TRANSFERS EAT GARBAGE PAST THIS (UP TO 256) * * * * COMMAND INTERPRETER INPUT BUFFER * * (THIS BUFFER IS HERE TO SOLVE MEMORY PROTECT PROBLEMS) * CBUF RES NMLEN+2+1 * * * * DIRECTORY SEARCH BUFFER DIBUF RES SECTSZ 500 BYTES * * * HEADER OFFSET VAUES FOR DIBUF * DINE EQU DIBUF NUMBER OF ENTRIES DIND EQU DIBUF+1 NEXT ENTRY DISPLACEMENT (2 BYTES TO ADDR 500) DRFDS EQU DIND+2 ADDRESS OF FIRST ENTRY * * * * NEXT FILE ID BUFFER * IDBUF RES NIDBC * * * * TRACK MAP BUFFER * TMBUF RES 8 FOR UNPACKED TRACK MAP * * * * COMMAND INTERPRETER STACK * CISS RES 50 FOR CI STACK CISTK EQU CISS+50 CI STACK * * * DIRECTORY ENTRY BUFFER * DEBUF RES NMLEN NAME DETYP RES 1 TYPE DEBBS RES 2 BLOCK SIZE IN BYTES DEPRO RES 1 PROTECTION ATTRIBUTES DEFID RES 2 FILE ID DEINX RES 2 FILE INDEX DEFBA RES 2 FIRST BLOCK DISK ADDRESS DENBL RES 2 NUMBER OF BLOCKS * DRESZ EQU DENBL+2-DEBUF ENTRY SIZE * PAGE * * ******************************************* * * * * FCB ENTRY FORMAT, CURRENT FCB ENTRY * FCBORG RES 1 BEGINNING FTYPE EQU FCBORG FILE TYPE FBLKS RES 2 BLOCK SIZE FPROT RES 1 PROTECTION FID RES 2 FILE ID FINDX RES 2 INDEX ADDRESS FFBA RES 2 FIRST BLOCK ADDRESS FUNIT RES 1 UNIT FBUFA RES 2 BUFFER ADDRESS/UNBUFFERED FLAG FDLTA RES 2 DELTA ALLOCATION IN BLOCKS FDRIV RES 2 DRIVER POINTER FAIND RES 2 MEMORY ADDRESS OF FILE INDEX BLOCK OR -1 FNBD RES 2 NEXT BYTE DISPLACEMENT FBDL RES 2 BYTE DISPLACEMENT LIMIT FFLAG RES 1 DIRTY BLOCK FLAG FCURSC RES 2 CURRENT SECTOR ADDRESS FGSPR RES 1 GARYS SPARE FFORE RES 2 FORE POINTER FBACK RES 2 BACK POINTER FHID RES 2 ID FROM HEADER FPRST RES 1 PROTECTION/STATUS * * NOTES: * 1) FTYPE-FFBA MUST MATCH DETYP-DEFBA * 2) FFORE-FPRST MUST MATCH THE DISK HEADER * TSTV1 EQU FTYPE-FFBA TSTV2 EQU DETYP-DEFBA TSTV3 EQU FFORE-FPRST * * * LNFCB EQU FPRST+1-FCBORG FCB LENGTH * TSTV4 EQU LNFCB TSTV5 EQU FPRST+1-FCBORG * * THIS MUST AGREE OR ELSE! * PAGE * * ******************************************* * * * DISK INTERFACE CONTROL BLOCKS * * * TRANSFER DESCRIPTOR or BLOCK TRANSFER DESCRIPTOR * Used to describe all transfers between disk and memory by * by calling XFER in SAMDI (disk interface) at $F016. * On entry HL ^ to BXD. * CALL XFER transfer data bet disk and memory * JMP ERROR error return (HL ^ to BXD, error code in A) * .... standard return * * TDAD EQU $ TSEC RES 2 TBCNT RES 2 TFID RES 2 TBUF RES 2 TUNIT RES 1 * BXD EQU $ BXDEV RES 1 BXOP RES 1 BXRZ RES 2 BXFR RES 2 BXXA RES 2 BXRES RES 2 * * * * * INCOMING HEADER * The header exists on disk as the last 12 bytes of a block * When a block is read from the disk to memory the header is * transferred from the buffer to here by RDDSK. * IHEAD EQU $ IHBLK RES 2 BLOCK IHFOR RES 2 FORE POINTER IHBAK RES 2 BACK POINTER IHFID RES 2 FILE ID IHPRO RES 1 PROTECTION/BLOCK SIZE (# of blocks) IHSIZ RES 2 BLOCK SIZE ie # of bytes in a block IHSPR RES 1 RWBUF RES SECTSZ DATA PUT HERE AFTER BUFFER SO WRITTEN TOGETHE * * * OUTGOING HEADER * The filing header is written to disk as the last 12 bytes of * a block. When a block of a file is to be written the header * is assembled here, then transferred to the end of the block * by WRDSK. * OHEAD EQU $ OHBLK RES 2 SECTOR # (starts at 0) OHFOR RES 2 FORE POINTER OHBAK RES 2 BACK POINTER OHFID RES 2 FILE ID OHPRO RES 1 PROTECTION-SECTORS/BLOCK OHSIZ RES 2 BLOCK SIZE OHSPR RES 1 * ENPAR EQU $ END OF THIS * * MARES EQU 0A002H SYSTEM RESIDENT WILL START HERE * PAGE * * ******************************************* * * * * FILE 0 FCB * * * THIS FILE IS THE SYSTEM CONSOLE. IT IS USED FOR * DEFAULT INPUT AND CANNOT BE CLOSED. * * * THE INITIAL FCB'S ARE ASSEMBLED HERE AND MOVED * TO FCB0 (THEIR PROPER PLACE) WHEN THE SYSTEM IS * BOOTSTRAPPED. * * ORG SP1 INITIALLY HERE * * * FILE '0'--C/I INPUT FILE * DB 255 TYPE IS DEVICE DW BUFT BLOCK SIZE DB PWRI WRITE PROTECTED KEYBOARD DW -1 ID DW 0 INDEX DW 0 FIRST BLOCK DB 0 UNIT DW FCB0-BUFT BUFFER ADDRESS DW 0 DELTA DW TDRIV TTY DRIVER DW -1 ALTERNATE INDEX DW 0 NBD DW 0 BDL DB 0 FLAG DW 0 CURRENT SECTOR DB 0 FGSPR DW EOFCD FORE = EOF DW BOFCD BACK = BOF DW -1 FILE ID DB 0 PROTECTION * * * * FILE '1'--CI OUTPUT FILE * DB 255 TYPE DW BUFT2 BLOCK SIZE DB PREA READ PROTECTED TYPER DW -1 IDENTIFICATION DW 0 INDEX DW 0 FBA DB 0 UNIT DW FCB0-BUFT-BUFT2 DW 0 DELTA DW TDRIV DRIVER DW -1 ALTERNATE INDEX ADDRESS DW 0 NBD DW 0 BDL DB 0 FLAG DW 0 CUR SECT DB 0 FGSPR DW EOFCD FORE DW BOFCD BACK DW -1 ID DB 0 PROT * * * * UTILITY FILE RESIDES HERE (FILE '2') * DB 80H DW 1F4H DB 0 DW 8 DW 214 DW 210 DB 0 DW FCB0-BUFT-BUFT2-1F4H DW 0 DW DDRIV DW -1 DW 0 DW 0 DB 0 DIRTY FLAG DW -1 DB 0 DW 211 DW -1 DW 8 DB 0 PAGE * * ****************************************************** * * * ORG MARES SYSTEM RESIDENT <|----------------<<---<<---<<< AP1 EQU MARES STARTS HERE. * * * * * * * **** PTDOS SYSTEM ENTRY POINT **** * * * * SAVE REGISTERS AND DISPATCH TO OPERATION * * SYS DI . DISABLE INTERRUPTS FOR AWHILE SHLD UHL SAVE HL LXI H,0 SHLD WBUFSZ CLEAR LOCAL BUFFER FLAG DAD SP HL=SP LXI SP,UHL SET SYSTEM STACK POINTER PUSH D SAVE D,E PUSH B SAVE B,C PUSH PSW SAVE A,FLAGS PUSH H SAVE SP SPHL . RESTORE USER SP POP H GET RETURN ADDRESS MOV A,M INX H MOVE PAST IT PUSH H SAVE RETURN ADDR AGAIN STA OPER SAVE OPERATION LXI SP,UTOS RESTORE SP CALL TSTEI PUT THE INTERRUPTS BACK ON IF DESIRED * * VALIDATE OPERATION * LDA OPER GET OPERATION CPI MAXOP+1 JC SDISPT IF OK GO TO OPERATION * * ILLEGAL OPERATION * ERR0 CALL ERRL1 ILLEGAL OPERATION DB ERIOP * * * DISPATCH TO OPERATION * * LOOK UP IN TABLE * SDISPT LXI H,DISPA DISPATCH ADDRESS MOV E,A MVI D,0 HL <--DISPA+(2*A) DAD D DAD D MOV A,M INX H MOV H,M MOV L,A * * HL NOW CONTAINS THE DISPATCH ADDRESS * PCHL . GO TO OPERATION * * * * SYSTEM DISPATCH TABLE * * DISPA DW CREATE 0 DW OPEN 1 DW KILL 2 DW READ 3 DW WRITE 4 DW SPACE 5 DW EOF 6 DW CLOSE 7 DW CHTYP 8 DW CHATR 9 DW CHNAM 10 DW FINFO 11 DW SUNH 12 DW RETURN 13 DW USRES 14 DW ABURP 15 DW SEEK 16 DW RNDOM 17 DW CA 18 CLOSE ALL FILES OPERATION DW FCTRL 19 DRIVER CONTROL/STATUS DW USRES 20 DW DREAD 21 DW DWRITE 22 DW DSPACE 23 DW RETRAP 24 * PAGE * * ***************************************** * * * * NORMAL RETURN * * RESTORE USER REGISTERS AND STACK * NRET CALL RFCB DI . NO INTERRUPTS THROUGH HERE LHLD UTOS SPHL POP H GET USER RETURN ADDRESS INX H INX H INX H PUSH H MAKE IT NORMAL RETURN * NRE10 DI . NO INTERRUPTS LHLD UHL PUSH H PUT USER HL ON USER STACK LXI SP,UPSW POP PSW RESTORE A,FLAGS POP B RESTORE BC POP D RESTORE DE * * FINAL RESTORATION * LHLD UTOS SPHL . RESET USER STACK POINTER DCX SP DCX SP MOVE BACK TO HL POP H RESTORE HL PUSH PSW CALL TSTEI RESTORE INTERRUPTS IF NEEDED POP PSW RET . GO BACK TO CALL * PAGE * * ***************************************** * * * ERROR RETURN * * LEVELS ARE: * * 0 VERY SERIOUS - BAD FILES, DISK PROBLEMS * 1 SERIOUS - USER PROBLEM * 2 EOF/BOF - ALWAYS HAPPEN * ERRL0 LHLD FERR GET PROCESSOR ADDRESS JMP ERRLP * * ERRL1 LHLD AERR GET LEVEL 1 PROCESSER JMP ERRLP * * ERRL2 LHLD EERR GET LEVEL 2 ERROR PROCESSER * * ERRLP - RESTORE FCB, RELEASE BUFFER, AND RECORD ERROR # * ERRLP DI . NO INTERRUPTS FOR A BIT PUSH H SAVE TYPE OF HANDLING CALL RFCB RESTORE FCB, IF ANY CALL RIDBF CLEAN UP BUFFER POP H ERROR HANDLING TYPE POP D POINTER TO ERROR NUMBER FROM CALL LDAX D = ERROR # STA UA RETURN IT TO THE HANDLER OR USER * * IF HL IS ZERO, SYSTEM PROCESSES ERROR * IF HL IS -1, USER ERROR RETURN, ELSE JUMP THERE * ERRP XCHG . TYPE LHLD UTOS RESTORE USERS STACK SPHL INX D MOV A,E ORA D JZ NRE10 USER ERROR RETURN DCX D MOV A,E ORA D JZ ERRP7 SYSTEM HANDLES IT * * CHANGE RETURN ADDRESS TO HL FOR ERROR TRAP * POP H GET RID OF OLD RETURN PUSH D PUT IN TRAP ADDRESS JMP NRE10 GO LOOK NORMAL * * * SYSTEM ERROR HANDLER, FORGET ABOUT USER PROGRAM * ERRP7 POP H GET RETURN ADDRESS IN HL LDA UTIL SEE IF A UTILITY FILE IS GOING INR A (-1 IF NOT) JNZ ERRP8 OK, USE IT LDA OPER MOV B,A GET OPERATION IN B LDA UA GET ERROR NUMBER IN A CALL SYS GO AWAY AND DON'T COME BACK DB ABTOP ABORT * * * * EXPLAIN THE ERROR USING UTILITY * ERRP8 LDA UA STA ERCD SET ERROR CODE (OPER ALREADY SET) LDA OPER STA EOPR SET OPERATION CODE * ERRPX PUSH H LXI H,XTRP TRAP ANY SERIOUS ERRORS SHLD AERR SHLD FERR POP H MVI A,3 (=> NUMBER AND "CALLER FROM" MSG.) JMP ERRP9 * PAGE * * ***************************************** * * * * * CREATE FILE OPERATION * * * USER DE POINTS TO A BLOCK WITH THE FOLLOWING FORM.... * * BYTE CONTENTS * 0 FILE TYPE * 1-2 FILE BLOCK SIZE * 3 FILE PROTECTION WORD * 4 ..... FILE NAME <0> OR NAME/UNIT # * * * ERRORS: * FILE ALREADY EXISTS * DIRECTORY FULL * MEMORY OVERFLOW * DISK FULL * ILLEGAL NAME * * FIRST, SEARCH DIRECTORY FOR FILE * CREATE LHLD UDE GET NAME POINTER LXI D,DEPRO-DETYP+1 DAD D CALL SDIR SEARCH JMP CRE10 NOT FOUND, OK CALL ERRL1 ERROR DB ERAEX * * CHECK FOR FULL DIRECTORY * CRE10 LHLD DFC MOV A,L ORA H JZ ERDIR FREE PTR IS ZERO - ERROR * * CREATE A DIRECTORY ENTRY IN DEBUF * COPY CONSTANT PARAMETERS * LHLD UDE XCHG . PARAMETER PTR IN DE LXI H,DETYP BUFFER PTR IN HL CALL MOVEF MOVE USER PARAMETERS DB DEPRO-DETYP+1 * * ALLOCATE BUFFER FOR INITIAL BLOCK ALLOCATION * LHLD DEBBS SHLD FBLKS PUT BLOCK SIZE INTO FCB * * PICK SOMEWHERE FOR A BUFFER JUST USE ANYWHERE * LHLD LOWAD SHLD TBUFA SAVE ADDRESS * * ALLOCATE FILE ID * CALL GFID XCHG SHLD DEFID SAVE ID IN DIREC. ENTRY * * SETUP PSEUDO FCB FOR CALL TO AFBLK * SHLD FHID SAVE ID LXI H,EOFCD SET EOF SHLD FFORE LXI H,BOFCD AND BOF SHLD FBACK XRA A =0 STA FPRST SET NOT DIRTY * * ALLOCATE BLOCK * CALL AFBLK SHLD DEFBA SAVE FIRST BLOCK ADDR IN DIREC. LXI H,1 SHLD DENBL SET NUMBER OF BLOCKS TO 1 DCX H MAKE HL=0 SHLD DEINX SET NO INDEX * MAKE DIRECTORY ENTRY CALL EDIR JMP NRET RETURN TO USER * * CERR1 CALL ERRL1 DIRECTORY FULL DB CER1 * PAGE * * ***************************************** * * * * DELETE (KILL) FILE OPERATION * * * USER DE POINTS TO NAME * * ERRORS: * FILE DOES NOT EXIST * FILE IS DELETE-PROTECTED OR OPEN * MEMORY OVERFLOW * * KILL LHLD UDE CALL SDIR SEARCH DIRECTORY JMP KIL90 ERROR - NONEXISTENT * * CHECK FOR DELETE PROTECTION * LDA DEPRO ANI PDEL DEL. PROT. BIT JNZ EOFE0 ERROR - PROTECTED * * CHECK IF FILE IS OPEN * LHLD DEFID FILE ID SHLD FID SET SO RBLK WILL WORK CALL SFCBS JMP KIL91 FOUND, OPEN ERROR JMP KIL91 FOUND * LHLD DEBBS SHLD FBLKS SETUP BLOCK SIZE FOR DEALLOCATION XCHG CALL ALBUF GET A BUFFER SHLD TBUFA * CALL RDIR REMOVE DIREC ENTRY * * RELEASE DISK SPACE * LHLD DEFBA SHLD FCURSC NOW, DISK ADDR, ID, AND BLK SZ SET LXI H,DDRIV SET DRIVER SHLD FDRIV ADDRESS IN FCB XRA A =0 STA FFLAG SET NOT DIRTY CALL RBLK READ FIRST BLOCK * * RELEASE EACH BLOCK * KIL20 CALL RFBLK RELEASE CALL DDRNB READ NEXT BLOCK JMP KIL50 EOF, DONE JMP KIL20 * * RELEASE BUFFER * KIL50 LHLD FBLKS XCHG LHLD TBUFA CALL DLBUF RELEASE IT * * RELEASE FILE INDEX * LHLD DEINX GET INDEX POINTER MOV A,H ORA L JZ NRET NONE SHLD FCURSC SET ESECT TO RET MVI A,1 STA FPRST SECTOR COUNT IS 1 CALL RFBLK RELEASE BLOCK JMP NRET DONE * * KIL90 CALL ERRL1 NONEXISTENT DB ERNEX KIL91 CALL ERRL1 FILE OPEN DB ERMOP * PAGE * * ******************************************* * * * * * OPEN FILE OPERATION * * * USER DE POINTS TO NAME * USER HL HAS BUFFER OPTIONS: * * IF -1 THEN UNBUFFERED * IF 0 THEN SYSTEM BUFFERED * ELSE USER BUFFERED * * * ON NORMAL RETURN, * A HAS THE FILE NUMBER * B HAS THE FILE TYPE, AND IF A=255: * * DE HAS THE DRIVER SIZE * HL HAS THE DRIVER LOAD ADDRESS * * * ERRORS: * FILE DOES NOT EXIST * NO FCBS AVAILABLE * MEMORY OVERFLOW * ILLEGAL USER BUFFER ADDRESS * * * * FIRST, LOOK UP FILE * OPEN LHLD UDE CALL SDIR JMP KIL90 DOESN'T EXIST * * FOUND, ALLOCATE FCB * LXI H,0 SHLD FRADD CALL ALFCB * * MOVE STUFF FROM DIRECTORY ENTRY TO FCB * LHLD DBUF LXI D,DETYP-DEBUF DISPLACEMENT TO TYPE DAD D XCHG . DE GETS SOURCE LXI H,FTYPE HL GETS DESTINATION CALL MOVEF DB DEFBA-DETYP+2 * LXI H,0 SHLD FNBD SET NBD=O SHLD FDLTA SET DELTA=O DCX H = -1 SHLD FAIND SET FAIND = -1 LHLD FFBA FIRST BLOCK ADDRESS SHLD FCURSC MAKE IT CURRENT BLOCK XRA A STA FFLAG CLEAR DIRTY FLAG * LXI H,DDRIV SHLD FDRIV SET DRIVER CALL OBUF JMP OPE70 UNBUFFERED * FILE IS BUFFERED CALL RBLK LOAD IN FIRST BLOCK SHLD FBDL SET BDL, (NBD=0) * OPE70 CALL LODRI SET UP DRIVER LHLD FRAD2 SHLD FRADD * * IF ALREADY OPEN, DON'T ALLOW NEW ALLOCATIONS * LHLD FID CALL SFCBS CHECK FOR OTHER FCB'S WITH SAME ID, UNIT JMP OPE75 YES JMP OPE75 YES, = 1 ALREADY JMP NRET NO, THIS WILL BE THE FIRST * * * * FILE ALREADY OPEN, SET PALO * OPE75 LDA FPROT FILE ALREADY OPEN, ORI PALO NO ALLOCATION ALLOWED. STA FPROT JMP NRET * * * CHECK FOR UNBUFFERED * OBUF LHLD UHL USER HL MOV D,H MOV E,L MAKE COPY IN DE INX D DE IS 0 IF UNBUFFERED MOV A,D ORA E ZERO TEST JZ OPE60 YES, UNBUFFERED * * CHECK FOR SYSTEM BUFFER REQUEST * MOV A,H ORA L IS IT ZERO JZ OPE40 YES, ALLOCATE SYSTEM BUFFER * * (S)HE HAS SPECIFIED A USER BUFFER * VALIDATE ADDRESS * XCHG LHLD FBLKS XCHG . DE = BLOCKSIZE, HL -> BUFFER CALL MEMCHK CHECK * OPE20 LHLD UHL * * COME HERE WITH BUFFER ADDRESS IN HL * OPE30 SHLD FBUFA SHLD TBUFA JMP RP2 RETURN CALL PLUS 2 * * * ALLOCATE SYSTEM BUFFER * OPE40 LHLD FBLKS XCHG CALL ALBUF ALLOCATE BUFFER JMP OPE30 GOT IT * * * FILE IS UNBUFFERED * OPE60 LXI H,-1 SHLD FBUFA RET * PAGE * * ****************** * * * * * ALLOCATE FILE CONTROL BLOCK * * NO PARAMETERS * * CALL ALFCB * RETURN FRADD SET, UA GETS NUMBER * ABORT IF NO FCB IS AVAILABLE * ALFCB LHLD FCBASE LXI D,FID-FCBORG DAD D FORM FID ADDRESS OF UST FCB LDA NFCB MOV C,A C = COUNT MVI B,-1 START WITH ZERO * ALF10 INR B COUNT UP MOV A,M GET ID INX H ORA M JZ ALF50 FOUND ONE LXI D,LNFCB-1 DAD D MOVE TO NEXT FCB DCR C COUNT DOWN JNZ ALF10 * * ABORT, NONE AVAILABLE * CALL ERRL1 LEVEL 1 DB ERTOP * * FOUND ONE * ALF50 MOV A,B STA UA LXI D,FCBORG-FID-1 DAD D MOVE BACK SHLD FRAD2 SET ADDRESS RET * PAGE * * ***************************************** * * * * "LODRI" CHECK IF DEVICE FILE AND LOAD IF SO * LODRI LDA FTYPE GET FILE TYPE STA UB RETURN TO CALLER IN "B" INR A CHECK FOR DEVICE FILE RNZ . ASSUMPTIONS SOMETIMES PROVE OUT * * * * LOAD A DEVICE DRIVER * * * THE FILE IS A DEVICE FILE. IT'S TIME TO LOAD IT. * THE DRIVER FILE IS AN IMAGE STRUCTURED FILE WHOSE * FIRST LOAD ADDRESS IS THE DRIVER TABLE ADDRESS. * ONLY A SINGLE BLOCK IS LAODED AND,OF COURSE, THE * START ADDRESS, IF ANY, IS NOT PROCESSED. * * * LOD20 CALL PBUF PREPARE THE BUFFER AND SAVE UBC,UDE * * NOW READ THE BLOCK. THE FIRST FILE BLOCK CONTAINS * THE COUNT AND LOAD ADDRESS SO IS SPECIAL. * LHLD FBDL LXI D,-4 DAD D JNC LER2 THE FILE DOESN'T EVEN HAVE FOUR BYTES!! * SHLD LCNT LCNT=FBDL-4 LHLD TBUFA CALCUALATE SOURCE ADDESS LXI D,4 DAD D SHLD SOU SOU=TBUF+4 * * PICKUP COUNT AND LOAD ADDRESS * XCHG DCX D BACKUP TO LAST BYTE OF ADDRESS LDAX D MOV H,A SET HIGH OF ADDRESS DCX D LDAX D MOV L,A LOW OF ADDRESS SHLD UDE SET LOAD ADDRESS * * NOW GET COUNT * DCX D LDAX D MOV H,A GET H OF COUNT DCX D LDAX D MOV L,A GET L OF COUNT SHLD UBC SET BLOCK COUNT ORA H JZ LER2 ERROR--ZERO BLOCK COUNT * * SAVE SIZE, LOAD ADDRESS FOR RETURN TO THE USER * PUSH H COUNT LHLD UDE PUSH H ADDRESS XRA A STA DELFG NO DELIMITER, PLEASE! * * NOW LOOP AND MOVE THE BLOCK * LOD30 LHLD UDE DESTINATION ADDEESS SHLD DEST SET IT LHLD LCNT XCHG . DE HAS LOCAL COUNT LHLD UBC HL HAS GLOBAL COUNT CALL MBLK LHLD UBC CHECK FOR LOAD COMPLETED MOV A,H ORA L JZ LOD40 COMPLETED--COUNT NOW ZERO * * READ IN NEXT BLOCK AND SET UP TRANSFER * LHLD FBLKS CALL RDNB READ NEXT BLOCK JMP LER3 EOF, ERROR LHLD TBUFA SHLD SOU SET SOURCE TO BUFFER LHLD FBDL SHLD LCNT SET LOCAL OUNT JMP LOD30 MOVE NEXT BUFFER LOAD * * * NEXT SET THE DRIVER ADDRESS IN THE FCB AND THROW * AWAY THE BUFFER USED TO READ THE FILE. * LOD40 POP H ADDRESS WAS THE THE STACK,REMEMBER PUSH H BUT KEEP IT SHLD FDRIV CALL CLBUX CLOSE OUT BUFFER * * GET NEW BLOCK SIZE FOR DEVICE AND REPROCESS BUFFER * LHLD FDRIV LXI D,DTBLK DAD D HL POINTS TO BLOCK SIZE MOV E,M INX H MOV D,M GOT IT IN DE XCHG SHLD FBLKS SET NEW BLOCK SIZE CALL OBUF OPEN A BUFFER NOP . YES THESE ARE REQUIRED..... NOP NOP * * FINALLY SET UP THE FCB FOR USE * LXI H,0 SHLD FNBD NBD=0 SHLD FBDL BDL=0 SHLD FINDX INDEX PTR TO ZERO DCX H MINUS ONE SHLD FBACK BACK IS BOF MOV A,H STA FUNIT SET UNIT=255 LXI H,EOFCD SHLD FFORE FORE IS EOF * * SET UBC,UDE TO REPORT BACK TO CALLER * POP H FROM STACK SHLD UDE POP H AREN'T STACKS WONDERFUL SHLD UBC * * INITIALIZE THE DRIVER * CALL DVBR INITIAL ENTRY DB DTINI * RET * * * ERRORS ERRS ERS * LER2 CALL ERRL1 BAD DRIVER--ZERO COUNT DB ERZBC * LER3 CALL ERRL1 BAD DRIVER--EOF DB EREOF * ****************** * * * * DISK DRIVER INTERFACE TO SYSTEM * * DDRIV DW DDRBL READ BLOCK DW DDRNB READ NEXT BLOCK DW DDRLB READ LAST BLOCK DW DDWBR WRITE/READ BLOCK DW DDWBL WRITE BLOCK DW DDREW REWIND DW DDEOF ENDFILE DW DDCLO CLOSE DW DDSEK SEEK DW DDCTL CONTROL DW 0 BUFFER SIZE DB 0 ITO (DO NOT CHANGE) DW DDCLO INITIALIZE DDCLO RET * IDAC CALL ERRL1 ILLEGAL DRIVER OPERATION DB ERIDA * PAGE * * ******************************************* * * * * * FILE READ/WRITE PROCESSER * * USER A - HAS FILE NUMBER * USER BC - HAS TRANSFER COUNT * USER DE - HAS SOURCE/DESTINATION ADDRESS * USER L - DELIMITER (IF DREAD OR DWRITE ENTRY) * * USES RWF, SOU, DEST, LCNT FOR TEMP STORAGE * * ERRORS: * * ILLEGAL FILE NUMBER * READ/WRITE PROTECTED FILE * EOF * DISK FULL * OTHER, MORE SERIOUS ERRORS * * DELIMITED READ ENTRY POINT * DREAD MVI A,-1 DEFLG GETS THIS RWF GETS 0 JMP RWP00 SET THE TWO FLAGS * * WRITE ENTRY POINT * WRITE XRA A RWP00 STA DELFG SET DELIMETER CMA . NOW INVERT THE FLAG JMP RWP02 AND SET THE READ/WRITE FLAG * * DELIMITED WRITE ENTRY POINT * DWRITE MVI A,-1 JMP RWP01 * * READ ENTRY POINT * READ XRA A =0 RWP01 STA DELFG THE DELIMITED FLAG RWP02 STA RWF THE READ/WRITE FLAG * * PREPARE FCB, ETC. * READ ENTRY POINT * CALL PFCB PREPARE THE FCB * * CHECK PROTECTION * RWCON LDA RWF ORA A JZ RWP10 READ * * CHECK AND REPORT WRITE PROTECT * CALL PROTST DB PWRI JMP RER0 ERROR - WRITE PROTECT JMP RWP20 OK * * CHECK AND REPORT READ PROTECT * RWP10 CALL PROTST DB PREA JMP RER0 ERROR - READ PROTECTION LHLD UBC XCHG . DE = COUNT LHLD UDE HL = ADDRESS CALL MEMCHK CHECK FOR WRITE INTO PROTECTED MEMORY * * PREPARE BUFFER * RWP20 CALL PBUF * SET UP TRANSFER OR RESTART AFTER NEW BUFFER LOAD RWP22 LHLD FNBD GET NEXT BYTE DISPLACEMENT XCHG LHLD TBUFA BUFFER ADDRESS DAD D HL = BUFF+NBD = SOURCE XCHG LHLD UDE = USER ADDRESS LDA RWF = READ/WRITE FLAG ORA A JZ RWP25 READ * * WRITE, INTERCHANGE SOURCE AND DEST * XCHG * RWP25 SHLD DEST SAVE DEST XCHG SHLD SOU AND SOURCE LHLD FNBD XCHG . DE MUST HAVE FNBD FOR RWP26 LHLD FBLKS = BLOCK SIZE * * IF WRITE, USE BLOCKSIZE AS BDL, ELSE BDL * JNZ RWP26 LHLD FBDL * * DE HAS NBD, HL HAS BDL OR BLOCK SIZE * COMPUTE HL-DE AS LOCAL COUNT * RWP26 CALL ARITH HL=HL-DE SHLD LCNT SAVE LOCAL COUNT XCHG . DE HAS LOCAL COUNT * * TEST IF COUNT IS ZERO (DE HAS LCNT) * RWP30 LHLD UBC MOV A,H ORA L JZ RWP70 YES, COUNT IS 0 --DONE * * SEE IF DELIMITER SEEN * LDA DELFG DCR A JZ RWP70 YES!, STOP TRANSFER * * TEST IF LOCAL COUNT IS ZERO * MOV A,D ORA E JNZ RWP50 NON-ZERO, MOVE DATA * * LOCAL COUNT IS ZERO * CALL UPBDL UPDATE BDL LDA RWF ORA A READ OR WRITE? JNZ RWP40 WRITE * READ LHLD FBLKS READ CALL RDNB READ NEXT BLOCK JMP EOFER EOF HIT JMP RWP22 CONTINUE THE READ * * * WRITE * RWP40 LHLD FBDL CALL WDBR WRITE BLOCK JMP RWP22 AND ONWARD * * * COUNT IS ZERO, OPERATION IS COMPLETE * UPDATE BDL IF NECESSARY * * WE CAN ALWAYS CALL FDB EVEN IF OPER=READ * IF WE ASSUME READ DIDN'T SET DIRTY * RWP70 CALL UPBDL CALL FDB YES, FLUSH DEVICE BUFFER CALL RBUF RELEASE BUFFER JMP NRET NORMAL RETURN WHEN DONE * * * UPDATE BDL * UPBDL LHLD FBDL XCHG LHLD FNBD CALL COMP CHECK BDL AND NBD RNC . BDL GE NBD SHLD FBDL UPDATE BDL RET * * * SET DIRTY IF WRITING * RWP50 CALL MBLK LHLD LCNT XCHG . DE GETS NEW LOCAL COUNT FOR LATER LDA RWF ORA A JZ RWP30 NOT WRITE STA FFLAG IT'S WRITE SET DIRTY FLAG JMP RWP30 * ********************* * * CALCULATE HL = HL-BC * RWPS MOV A,L SUB C MOV L,A MOV A,H SBB B MOV H,A RET * * * CALCULATE HL = HL-DE * ARITH MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A RET ***************************************** * * * CHECK FOR READ OR BUFFER IN PROTECTED AREAS * * ON CALL HL HAS START ADDRESS * DE HAS COUNT * * ON RETURN, ALL REGISTERS DESTROYED; ABORT IF ERROR * MEMCHK DCX D LOWER COUNT FOR PROPER TESTS PUSH D SAVE COUNT LXI D,SYSTOP TOP OF SYSTEM CALL COMP DO COMPARE POP D JNC MEMC0 IF START ADDRESS LESS THAN TOP OF SYSTEM * * START IS ABOVE SYSTEM. OK IF IT DOESN'T PASS ZER0 * DAD D HL= TOP OF WRITE MOV A,H GET HIGH BYTE ORA A RM . STILL MINUS....OK * MERR1 CALL ERRL1 DB ERMEM USER MEMORY PROTECT ERROR * MEMC0 PUSH H ADDRESS PUSH D COUNT DAD D HL GETS HIGEST USED ADDRESS XCHG . TO DE LHLD LOWAD GET LOWEST SYSTEM ADDRESS CALL COMP POP H COUNT TO HL POP D START ADDRESS MOV B,H MOV C,L SAVE COUNT IN BC JC MEM10 DE .LT. LOWAD OK STILL * * ATTEMPTING TO WRITE INTO SYSTEM..SEE IF CBUF * LXI H,CBUF CALL COMP DE HAS WRITE ADDRESS JNZ MERR2 IF IT WASN'T CBUF * * NOW TEST COUNT FOR 256 OR LESS * LXI H,-256 DAD B BC = COUNT RNC . IF COUNT .LT. 256 * MERR2 CALL ERRL1 DB ERSMP SYSTEM MEMORY PROTECT * * * SEE IF ABOVE USER PROTECT * MEM10 LHLD UPROT DE HAS MEMORY WRITE START CALL COMP RNC . HL .GE. DE (START <= UPROT ), OK JMP MERR1 USER MEMORY PROTECT * * ********************* * * * MOVE DATA * * COME HERE WITH LOCAL COUNT IN DE, GLOBAL IN HL * MBLK CALL COMP JNC RWP52 DE => HL, USE GLOBAL COUNT XCHG . USE LOCAL COUNT * RWP52 CALL CKDEL CHECK FOR DELIMITER MOV B,H MOV C,L COUNT IN BC * LHLD UDE UPDATE NUMBERS DAD B SHLD UDE SOU/DEST ADDRESS LHLD UBC CALL RWPS SHLD UBC USER COUNT LHLD LCNT CALL RWPS SHLD LCNT LOCAL COUNT LHLD FNBD DAD B SHLD FNBD NBD * LHLD SOU XCHG . DE HAS SOURCE LHLD DEST HL HAS DESTINATION JMP MOVEV BC HAS COUNT, MOVE AND RETURN * ********************* * * * CHECK FOR DELIMITER * * SET FLAG IF FOUND * HL = COUNT * RETURN, HL = POSSIBLY REDUCED COUNT, DELFG SET * CKDEL LDA DELFG ORA A SEE IF CHECKING FOR DELIMITERS AT ALL RZ . NO PUSH H XCHG LHLD SOU HL -> DATA, DE = MAX COUNT * * LOOP FOR END OF COUNT OR DELIMITER * CKD20 MOV A,D TEST IF OUT OF COUNT ORA E JZ CKD30 * DCX D ACCOUNT FOR THIS ONE LDA UL = DELIMITER CMP M JZ CKD50 FOUND! INX H JMP CKD20 LOOP * * END OF COUNT... NOT FOUND * CKD30 POP H RESTORE COUNT RET * * * FOUND, COMPUTE UPDATED COUNT * CKD50 POP H MOV B,D MOV C,E DECREMENTED COUNT IN BC CALL RWPS HL=HL-BC MVI A,1 STA DELFG SET FLAG RET . ALL SET * PAGE * * ******************************************* * * * * * READ SINGLE BYTE OPERATION * * "A" HAS THE FILE NUMBER * * THIS OPERATION USES THE USER STACK. THE * STANDARD ENTRY AND EXIT ROUTINES ARE NOT USED. * * ERRORS: * ILLEGAL FILE NUMBER * PROTECTED FILE * EOF * RB CALL RWPREP SAVE A BUNCH OF JUNK AND PREPARE CALL PROTST CHECK IF PROTECTED DB PREA * JMP RER0 ERROR - PROTECTED CALL PBUF PREPARE BUFFER * * CHECK IF BUFFER EMPTY * LHLD FNBD XCHG LHLD FBDL BBD BDL CALL COMP COMPARE DE HL JC RB50 NBD LT BDL, OK * * FILL BUFFER * LHLD FBLKS CALL RDNB JMP RBEOF * * LOAD BYTE AND UPDATE NBD * RB50 CALL UPNBD GET THE BUFFER ADDRESS AND COUNT UP MOV A,M STA UA SAVE BYTE CALL RBUF RELEASE BUFFER CALL RFCB RESTORE FCB LDA UA RETURN WITH BYTE IN A * * * EVERYONE COMES HERE FOR CALL+2 * RETURN THROUGH HL * RP2 POP H RP3 INX H INX H INX H PCHL . NORMAL RETURN * * * PROTECTED * RER0 CALL ERRL1 DB ERPRO * ********************* * * * PREPARE FOR READS AND WRITES * RWPREP STA UA SAVE FILE NUMBER IN USER A MOV A,B STA UB WRITE USES THIS LXI H,0 SHLD WBUFSZ CLEAR DANGLING BUFFER FLAG DAD SP INX H INX H SHLD UTOS SET UTOS FOR ERRORS JMP PFCB PREPARE FCB AND RETURN * * * UDATE NEXT BYTE DISPLACEMENT AND RETURN BUFFER ADDRESS * UPNBD LHLD FNBD GET NEXT BYTE DISPLACEMENT INX H BUMP IT FOR THIS BYTE SHLD FNBD DCX H ADJUST COUNT TO POINT TO CURRENT POSITION XCHG LHLD TBUFA DAD D HL = NBD + BUFF ADDRESS RET * PAGE * * ******************************************* * * * * * WRITE SINGLE BYTE OPERATION * * A HAS THE FILE NUMBER * B HAS THE BYTE * * * ON RETURN, * A,B ARE UNCHANGED * * THIS OPERATION USES THE USER STACK. STANDARD ENTRY, * EXIT, AND ERROR ROUTINES ARE NOT USED * * ERRORS: * ILLEGAL FILE NUMBER * PROTECTED FILE * DISK FULL * * * WB CALL RWPREP PREPARE EVERYTHING CALL PROTST CHECK PROTECTION DB PWRI JMP RER0 ERROR - PROTECTED CALL PBUF PREPARE BUFFER * * CHECK FOR FULL BLOCK * LHLD FNBD XCHG LHLD FBLKS NBD BLOCK SIZE CALL COMP COMPARE DE HL JC WB50 NBD LT BLOCKSIZE CALL WDBR BUFFER IS FULL...WRITE IT * * STORE BYTE, UPDATE NBD * WB50 CALL UPNBD LDA UB MOV M,A STORE BYTE MVI A,1 STA FFLAG SET DIRTY * * UPDATE BDL IF NECESSARY * INX D LHLD FBDL DE HAS NBD CALL COMP JC WB60 NBD LT BDL, LEAVE BDL ALONE XCHG SHLD FBDL UPDATE BOL * * FINISH UP * WB60 CALL FDB FLUSH BUFFER IF DEVICE FILE CALL RBUF RESTORE BUFFER CALL RFCB RESTORE FCB LDA UB MOV B,A SET B LDA UA RESTORE A JMP RP2 * PAGE * * ******************************************* * * * * * MOVE FILE POINTER OPERATION (SPACE) * * UA HAS FILE NUMBER * UBC HAS DELTA VALUE * UD= 0 FOR REWIND * -1 FOR SPACE-TO-END * 1 FOR SPACE FOREWARD * 200(8) FOR SPACE BACKWARDS * UL DELIMITER IF DSPACE * * * ERRORS: * ILLEGAL FILE NUMBER * EOF/BOF * * * DELIMITER SPACE ENTRY * DSPACE MVI A,-1 JMP SPA01 * * * STANDARD SPACE ENTRY * SPACE XRA A SPA01 STA DELFG SETUP DELIMITER SCAN FLAG CALL PFCB PREPARE FCB CALL PBUF PREPARE BUFFER CALL WDBUF FLUSH OUT ANYTHING LDA UD ORA A LOOK AT OPTIONS JNZ SPA20 NOT REWIND * * D=0...REWIND FILE * LHLD FBLKS GET BLOCK SIZE XCHG LHLD TBUFA DE=COUNT, HL->BUFFER CALL DVBR DO THE REWIND DB DTREW * SHLD FBDL GOOD, SET BDL FROM HEADER COUNT LXI H,0 SHLD FNBD JMP SPA80 * ********************* * * * (PART OF DISK INTERFACE) COME HERE TO REWIND DISK FILE * DDREW LHLD FCURSC CURRENT SECTOR AND TRACK XCHG LHLD FFBA FIRST SECTOR AND TRACK CALL COMP CHECK IF CORRECT BLOCK IS IN JZ REW10 YES SHLD FCURSC SET AS CURRENT SECTOR CALL RBLK PRIME WITH FIRST BLOCK RET . HL HAS COUNT IN SECTOR * * * CURRENT BLOCK IS IN * REW10 LHLD FBDL RETURN SIZE RET * * * SPACE FORWARD OR BACKWARD * SPA20 JP SPAF (S)HE WANTS FOREWARD INR A JNZ SPAB (S)HE WANTS BACKWARDS * * MOVE TO EOF * SPA22 LHLD FBLKS CALL RDNB READ NEXT BLOCK JMP SPA25 EOF JMP SPA22 TRY AGAIN * * SPA25 LHLD FBDL SHLD FNBD SET NBD=BDL JMP SPA80 GO QUIT * * * SPACE FOREWARD * SPAF LHLD FNBD XCHG . DE HAS NBD LHLD FBDL HL HAS BDL CALL ARITH HL=HL-DE XCHG . DE HAS BDL-NBD CALL UPCNT GET MAXIMUM COUNT TO HL PUSH H LHLD TBUFA COMPUTE -> DATA XCHG LHLD FNBD DAD D -> DATA SHLD SOU SET DATA SOURCE POINTER POP H GET BACK COUNT * * IF DELIMITED, DO PRESCAN FOR DELIMITER * CALL CKDEL FIND NEW COUNT IF DELIMITED XCHG . DE HAS MIN OF USER, LOCAL CNT. LHLD FNBD DAD D SHLD FNBD UPDATE NBD LHLD UBC CALL ARITH HL=HL-DE= NEW USER COUNT SHLD UBC UPDATE USER COUNT * * TEST FOR ZERO COUNT OR DELIMITER * ORA L "A" HAS "H" FROM ARITH JZ SPA80 YES, GO QUIT * LDA DELFG CHECK IF DELIMITER SEEN DCR A JZ SPA80 YES, GO QUIT * * NO, MOVE TO NEXT BLOCK * CALL RDNB MOVE TO NEXT JMP SEOF EOF JMP SPAF * ********************* * * * FIND MIN OF UBC, AND DE INTO HL * UPCNT LHLD UBC CALL COMP RNC . HL GE DE XCHG . DE LT HL RET * ********************* * * SPACE REVERSE * SPAB LHLD FNBD SPABX XCHG . DE HAS NBD LHLD UBC CALL UPCNT HL GETS MIN OF DE,HL * * HL = MAX COUNT, THIS BUFFER * SCAN BACKWARD FOR DEL * LDA DELFG ORA A JZ SPA69 NO DELIMITER TO LOOK FOR, SKIP THIS JUNK * * CHECK FOR DELIMITER BACKWARDS * PUSH H MOV B,H MOV C,L BC = MAX COUNT LHLD TBUFA XCHG LHLD FNBD DAD D HL -> BUFFER END (NEXT CHAR) * SPA60 MOV A,B ORA C CHECK FOR ZERO COUNT JZ SPA63 YES, END OF BUFFER, NOT FOUND DCX H LDA UL = DELIMITER CMP M DCX B JNZ SPA60 TRY AGAIN INX B RESTORE THE COUNT * * FOUND THE DELIMITER...TIME TO QUIT * SPA65 POP H CALL RWPS HL = HL - BC MVI A,1 STA DELFG SET DELIM FOUND FLAG * * UPDATE NBD * SPA69 XCHG . BUFFER ADDRESS TO DE LHLD FNBD OLD BUFFER DISPLACEMENT CALL ARITH HL=HL-DE SHLD FNBD * * UPDATE USER COUNT (UBC) * LHLD UBC CALL ARITH HL=HL-DE SHLD UBC ORA L IS COUNT ZERO? A HAS H FROM ARITH JZ SPA80 YES, GO QUIT * LDA DELFG DCR A JNZ SPA81 DELIMITER NOT FOUND * * DONE, END OF COUNT OR DELIMITER FOUND * SPA80 CALL RBUF RELEASE BUFFER JMP NRET * * * READ LAST SECTOR * SPA81 LHLD FBLKS XCHG LHLD TBUFA CALL DVBR READ LAST BLOCK DB DTRLB * JMP SEOF EOF SHLD FBDL SET SIZE SHLD FNBD AND PTR TO END JMP SPABX CONTINUE * * * NOT FOUND IN THIS BUFFER * SPA63 POP H JMP SPA69 MAKE LIKE NOTHING HAPPENED * * * EOF * SEOF CALL RBUF CALL ERRL2 ERROR DB EREOF * EOFER EQU SEOF RBEOF EQU SEOF * PAGE * * ******************************************* * * * * * CLOSE FILE OPERATION * * UA HAS FILE NUMBER * THE FCB IS RELEASED * * ERRORS: * ILLEGAL FILE NUMBER * * * CLOSE LDA UA GET FILE NUMBER LXI H,SYSFIL CMP M JC NRET OK, IT'S DONE BUT NOT SO!!! CALL PFCB CALL CLOSIT CLOSE THE FILE JMP NRET DONE * ********************* * * * CLOSE FILE SUBROUTINE * * COME HERE WITH CURRENT FCB SET * CLOSIT CALL CLBUF CLOSE BUFFER LHLD FDLTA MOV A,H ORA L NO CHANGE... NOT NEEDED JZ CLO30 LHLD FID CALL SDIRX SEARCH DIRECTORY BY ID * * UPDATE FILE SIZE * LHLD DBUF LXI D,DENBL-DEBUF DISPLACEMENT TO SIZE DAD D XCHG LHLD FDLTA GET NUMBER BLOCKS ALLOCATED LDAX D ADD L UPDATE STAX D FILE INX D SIZE LDAX D IN ADC H BLOCKS STAX D CALL WDSK REWRITE DIRECTORY * CLO30 LXI H,0 SHLD FID RELEASE THE FILE CONTROL BLOCK RET * ********************* * * * WRITE DIRTY BLOCK AND DEALLOCATE BUFFER * CLBUF LHLD FBUFA INX H MOV A,H ORA L RZ . UNBUFFERED, NOTHING TO DO DCX H SHLD TBUFA SET TBUFA FOR UTILITIES CALL WDBUF FLUSH BUFFER CALL DVBR TAKE CLOSE DRIVER DB DTCLO ENTRY * * COME HERE TO JUST RELEASE BUFFER * CLBUX LHLD FBUFA INX H MOV A,H ORA L RZ . UNBUFFERED, QUIT DCX H XCHG . DE HAS BUFFER ADDRESS LHLD MINAD HL HAS BOTTOM OF SYS GLOBAL CALL COMP RC . DE LT HL, USER BUFFER LXI H,SYSTOP NOW TOP OF SYSTEM CALL COMP RNC . DE GT HL USER BUFFER * * RELEASE BUFFER * LHLD FBLKS XCHG . DE HAS SIZE, HL HAS ADDRESS CALL DLBUF DEALLOCATE BUFFER RET * PAGE * * ******************************************* * * * * CLOSE MULTIPLE FILES * * UA = UNIT #<0-254> CLOSE ALL ON UNIT SPECIFIED * = 255 CLOSE ALL OPEN FILES * * ERRORS: NONE OTHER THAN DISK * * CA MVI A,0 STA CLCNT COUNT UP FROM ZERO THROUGH FCB'S LHLD FCBASE START AT FIRST FCB * * LOOP HERE WITH NEXT FCB (PNTR ON TOS) * CA20 PUSH H SAVE FCB POINTER * * SEE IF FILE # < SYSFIL * LXI H,SYSFIL LDA CLCNT CMP M IS FILE# < SYSFIL? JC CA50 YES, SKIP POP H PUSH H RESTORE HL * * CHECK FILE ID FOR A OPEN FILE FCB (REAL? OOOBOY) * LXI D,FID-FCBORG DAD D MOVE TO FID BYTES MOV A,M INX H ORA M CHECK IF ID=0 JZ CA50 YES, SKIP IT * * CHECK IF DESIRED UNIT * LXI D,FUNIT-FID-1 DAD D MOVE TO UNIT NUMBER LDA UA CPI 255 CLOSE ALL JZ CA30 YES CMP M CHECK IF THIS UNIT JNZ CA50 NOT THE ONE, LEAVE OPEN * * CLOSE CURRENT FILE * CA30 POP H GET POINTER TO FCB PUSH H CALL PFC6 SETUP FCB CALL CLOSIT CLOSE THE FILE CALL RFCB RESTORE FCB * * MOVE TO NEXT FILE * CA50 LXI H,CLCNT --> COUNTER INR M COUNT UP LDA NFCB = # OF FCB'S CMP M HAVE WE DONE EM ALL? JZ NRET YES, DONE * * STILL MORE * POP H LXI D,LNFCB DAD D MOVE TO NEXT FILE JMP CA20 AND LOOP * PAGE * * ******************************************* * * * * ENDFILE OPERATION * * UA HAS FILE NUMBER * * ERRORS: * ILLEGAL FILE NUMBER * PROTECTED FILE * * EOF CALL PFCB PREPARE FCB CALL PROTST DB PWRI JMP RER0 ERROR - PROTECTED FILE CALL PBUF PREPARE BUFFER LHLD FNBD SHLD FBDL SET BDL TO CURRENT POINTER XCHG LHLD TBUFA DE=CT, HL=BUF CALL DVBR CALL DRIVER DB DTEOF * EOF1A CALL WDB50 CLEAR THE DIRTY FLAG CALL RBUF RELEASE BUFFER JMP NRET RETURN * ********************* * * * DISK FILE CLOSE (PART OF DISK INTERFACE) * DDEOF LHLD FID CALL SFCBS JMP RER0 OPEN MORE THAN ONCE, ERROR JMP EOF10 OPEN ONCE, OK * EOF10 LHLD FFORE SHLD ETMP SAVE FORE PTR LHLD FNBD SHLD FBDL SET BDL,ALSO MOV A,H ORI 128 SET HIGH BIT MOV H,A SHLD FFORE SET EOF AND BYTE COUNT LHLD FCURSC SHLD ECRS SAVE CURRENT SECTOR CALL WBLK WRITE BLOCK * * RELEASE ALL BLOCKS PAST THIS ONE * LHLD ETMP SHLD FFORE RESTORE FORE PTR * EOF20 CALL DDRNB MOVE TO NEXT BLOCK JMP EOF50 EOF, DONE CALL RFBLK RELEASE BLOCK JMP EOF20 MOVE TO NEXT * * EOF50 LHLD FINDX GET INDEX FILE MOV A,H IS THERE AN INDEX ORA L JZ EOF60 NO, DONE CALL RBUF RELEASE BUFFER CALL RFCB YES,RESTRE FCB, THEN JMP RNDOM UPDATE INDEX * * EOF60 LHLD FCURSC TEST IF AT CORRECT BLOCK XCHG LHLD ECRS CALL COMP JZ EOF70 DON'T READ SHLD FCURSC CALL RBLK RESTORE CURRENT BLOCK SHLD FBDL SET BDL * EOF70 LHLD FBDL SHLD FNBD SET NBD JMP EOF1A * * EOFE0 EQU RER0 PROTECTED FILE * * PAGE * * ******************************************* * * * * * FILE INFORMATION REQUEST OPERATION * * * UDE POINTS TO NAME * UHL HAS DATA BLOCK ADDRESS * * ERRORS: * FILE DOES NOT EXIST * FILE IS PROTECTED * * FINFO LHLD UDE CALL SDIR SEE IF NAME EXISTS JMP FIN90 WE RETURN HERE IF NOT * * IT EXISTS.....CHECK FOR OVERWRITE INTO SYSTEM * LXI D,DRESZ+3 SIZE LHLD UHL USER SPECIFIED ADDRESS CALL MEMCHK * * OK, COPY DIREC ENTRY * LXI D,DEFID -> FILE ID LHLD UHL HL POINTS TO USER AREA CALL MOVEF MOVE DB DENBL-DEFID+2 THIS MANY WORDS * LXI D,DETYP -> FILE TYPE LHLD UHL LXI B,DENBL-DEFID+3+2 DAD B CALL MOVEF MOVE CREATE PARM PART DB DEPRO-DETYP+1 * LHLD DBUF -> NAME XCHG LHLD UHL LXI B,DENBL-DEFID+3+2+DEPRO-DETYP+1 DAD B CALL MOVEF MOVE NAME DB NMLEN * * SEE IF FILE IS OPEN * LHLD DBUF LXI D,DEFID-DEBUF DAD D HL POINTS TO FILE ID MOV E,M INX H MOV D,M XCHG . HL HAS FILE ID CALL SFCBS SEARCH....TRIPLE LEVEL RETURN JMP FIN20 YES JMP FIN20 YES XRA A NO JMP FIN21 * * * "A" HAS NUMBER OF FCBS * FIN20 MVI A,1 YES FIN21 LHLD UHL STORE A 1 PAST DIREC ENTRY LXI D,DENBL-DEFID+3 DAD D MOV M,A XRA A =0 LXI D,NMLEN+DEPRO-DETYP+1+1+1 DAD D MOV M,A PUT ZERO BYTE AFTER NAME JMP NRET ALL DONE * * FIN90 CALL ERRL2 DB ERNEX NONEXISTENT * PAGE * * ******************************************* * * * * * ALTER FILE CHARACTERISTICS OPERATIONS * * * USER DE ALWAYS POINTS TO NAME * * * * CHANGE FILE TYPE OPERATION * * ON CALL USER H HAS NEW TYPE * * ERRORS: * FILE DOES NOT EXIST * FILE IS PROTECTED * CHTYP CALL FFILE CHECK FOR PROTECTION (NAME AND TYPE) DB PNAT LDA UH STA DETYP CHANGE TYPE JMP UWFIL FINISH UP * ********************* * * * CHANGE ATTRIBUTES OPERATION * * USER H HAS NEW ONES * CHATR CALL FFILE DB PATR LDA UH STA DEPRO SET NEW PROTECTION JMP UWFIL * ********************* * * * CHANGE NAME OPERATION * * USER HL POINTS TO NEW NAME * CHNAM LHLD UHL CALL SDIR SEE IF NEW NAME EXISTS JMP CHN20 NO CALL ERRL1 YES DB ERAEX FILE ALREADY EXISTS * * CHN20 LDA FUNIT GET DEFAULT UNIT PUSH PSW CALL FFILE SET UP DB PNAT * * MOVE IN NEW NAME * POP H H=UNIT LDA FUNIT CMP H SAME? JNZ CHER1 NO, UNIT CONFLICT LHLD UHL CALL NAMIN READ IN NAME * * UPDATE DIRECTORY ENTRY FROM DEBUF, THEN * REWRITE DIRECTORY SECTOR AND RETURN. * UWFIL LXI D,DEBUF LHLD DBUF CALL MOVEF MOVE ENTRY BACK DB DRESZ CALL WDSK WRITE IT OUT JMP NRET THEN GO. * * * SEARCH FOR FILE AND SET UP * FFILE LHLD UDE HL POINT TO NAME CALL SDIR JMP KIL90 NONEXISTENT POP H LDA DEPRO ANA M INX H JNZ CHER0 ERROR...PROTECTED PCHL . OK, RETURN CALL+1 * * CHER0 CALL ERRL1 ERROR DB ERPRO * CHER1 CALL ERRL1 UNIT CONFLICT DB ERUCN * PAGE * * ******************************************* * * * * * SEEK OPERATION * * * USER A HAS FILE NUMBER * USER B = 0 => HL = BYTE# * <> 0 => HL = BLOCK# * USER HL HAS REQUESTED BYTE NUMBER * * ERRORS: * DEVICE FILE * FILE NOT RANDOM * TOO FAR IN FILE * EOF * * SEEK CALL PFCB CALL PBUF PREPARE BUFFER LHLD UHL PUSH H SAVE SEEK ADDRESS LHLD FBLKS XCHG LHLD TBUFA LDA UB GET BLOCK OPTIONS CALL DVBR DB DTSEK GO SEEK JMP SEKE1 OUT OF RANGE * CALL TO DVBR RETURNS HERE IF OK SHLD FBDL SET BDL XCHG SHLD FNBD AND NBD CALL RBUF DONE JMP NRET * ********************* * * * DISK INTERFACE FOR SEEK * * CHECK IF RANDOM INDEX EXISTS * THEN READ IT INTO DIRECTORY BUFFER IF NOT ALREADY IN * MEMORY * DDSEK LHLD FAIND SEE IF INDEX IN MEMORY SHLD RINAD ASSUME LOADED INX H (ITS -1 IF NOT) MOV A,H ORA L CZ RINDX LOAD AND SET RINAD IF NOT * * COMPUTE QUOTIENT AND REMAINDER OF UHL/FBLKS * LHLD FBLKS MOV B,H MOV C,L BC IS BLOCK SIZE POP H =RETURN ADDRESS XTHL . HL=SEEK POINT, STACK= RETURN ADDRESS LXI D,0 DE HAS QUOTIENT..IT WILL,IT WILL * * CHECK FOR SEEK BLOCK * LDA UB GET OPTION...BLOCK OR BYTE ORA A JZ SEK10 NO BYTE XCHG . DE = BLOCK# LXI B,0 LXI H,0 SET SO NBD = 0 EVENTUALLY JMP SEK20 * * * GO TO INDIVIDUAL BYTE * SEK10 CALL RWPS HL = HL - BC INX D JNC SEK10 DCX D * * GOT IT * SEK20 MOV A,D ORA A RNZ . ERROR, REQUESTED BLOCK .GT. 256 MOV A,E CPI 250 RNC . ERROR, ITS GE 250 DAD B HL IS REMAINDER PUSH H SAVE IT AS FUTURE NBD * * NOW FETCH INDEX ENTRY * LHLD RINAD -> INDEX BLOCK DAD D DAD D HL POINTS TO APPROPRITE ONE * * PICK IT UP * MOV E,M INX H MOV D,M PUSH D SECTOR/TRACK OF DISK ADDRESS PUSH H INDEX BLOCK ADDRESS LHLD FCURSC GET CURRENT SECTOR/TRACK CALL COMP COMPARE PUSH PSW SAVE FLAGS FOR LATER CNZ WDBUF WRITE OUT DIRTY BUFFER IF NOT SAME ADDRESS POP PSW POP D INDEX ADDRESS POP H DISK ADDRESS PUSH PSW * * IS DISK ADDRESS IN EXISTENCE YET * MOV A,H ORA L JZ SEX NO, PAST EOF ERROR, PROBABLY * * HL HAS ADDRESS OF NEW CURRENT BLOCK, NBD ON TOP OF STACK * SHLD FCURSC SAVE AS CURRNT ADDRESS POP PSW LHLD FBDL IN CASE WE DON'T READ IN THE BLOCK CNZ RBLK READ NEW BLOCK POP D * * DE=NBD, HL=BDL; CHECK NBD .LE. BDL * CALL COMP JZ RX2 OK, WE'RE AT THE EOF JC RX2 OK, WE'RE NOT AT THE EOF, BUT IN THE FILE RET . EOF ERROR, WE'VE GONE TOO FAR * ********************* * * * THERE ARE SOME NASTY SPECIAL CASES ABOUT SEEKING * TO THE END OF FILE. IT IS OK TO SEEK TO LAST BYTE +1, * BUT, UNFOUTUNATELY, A SPECIAL TEST MUST BE MADE TO * FORCE THE CURSOR INTO THE LAST LEGAL BLOCK INSTEAD * OF THE NEXT, NOT-YET-EXISTENT BLOCK. * * ADDRESS DIDN'T EXIST, SEE IF ALTERNATE ADDRESS AT * END OF LAST BLOCK APPLIES. * * FIRST, SETUP FOR PREVIOUS SECTOR * SEX XCHG . HL -> 1 BEYOND CURRENT DCX H DCX H POP PSW MOV A,M FOR H LATER DCX H MOV L,M MOV H,A ORA L TEST FOR EXISTENCE POP D KEEP STACK CLEAN RZ . NO, WE'RE DEFINITLY BEYOND EOF SHLD FCURSC WELL, MAYBE OK, LAST BLOCK EXISTS * * SEE IF NBD WAS ZERO, IF SO, COULD ALSO USE BDL OF LAST BL * MOV A,D ORA E RNZ . NOT ZERO, OUT OF RANGE * * OK, LOAD LAST BLOCK, SET NBD=BDL, BUT ERR IF NOT FULL * CALL RBLK XCHG LHLD FBLKS BDL MUST = BLOCK SIZE, ELSE OUT OF RANGE CALL COMP JZ RX2 OK RET . NO, GO BACK WITH ERROR * * SEKE0 CALL ERRL1 FILE NOT RANDOM DB ERRAC * SEKE1 CALL ERRL1 SEEK ADDRESS OUT OF RANGE DB ERSEK * ********************* * * * READ FILE INDEX * * ENTER AT RINDX TO READ INTO DIBUF * ENTER AT RINDY WITH HL -> WHERE TO LOAD * LOAD INDEX AND SET RINAD TO -> INDEX IN EITHER CASE * RINDX LXI H,DIBUF RINDY SHLD RINAD SET LOAD ADDRESS LHLD FINDX INDEX ADDRESS MOV A,H ORA L JZ SEKE0 ITS ZERO, ERROR * CALL STDAD SET XFER DESC.... LHLD FINDX SHLD TDAD LXI H,SECTSZ BLOCKSIZE IS 500 OR ELSE SHLD TBCNT LHLD RINAD SHLD TBUF READ INTO SPECIFIED ADDRESS JMP RDSK READ INDEX AND RETURN * PAGE * * ******************************************* * * * * MAKE FILE RANDOM OPERATION * * * CREATE IF NECESSARY AND UPDATE INDEX BLOCK * * * USER A HAS THE FILE NUMBER * * ERRORS: * DEVICE FILE * * RNDOM CALL PFCB PREPARE FCB LDA FTYPE CHECK FOR DEVICE FILE INR A JZ RNER0 YES...ERROR CALL PBUF PREPARE BUFFER CALL WDBUF CLEAN IT UP * * READ FIRST BLOCK * LHLD FFBA SHLD FCURSC CALL RBLK * * ZERO THE DIRECTORY BUFFER..DIBUF * MVI D,0 LXI B,SECTSZ COUNT=SECTSZ LXI H,DIBUF SHLD RNPTR RNPTR IS ''DIBUF'' * RND10 MOV M,D ZERO A WORD INX H DCX B COUNT DOWN MOV A,B ORA C JNZ RND10 * * CHECK IF FILE ALREADY HAS AN INDEX * LHLD FINDX MOV A,H ORA L JNZ RND20 YES... * * ALLOCATE AN INDEX BLOCK FOR THE FILE * LHLD FBLKS PUSH H SAVE BLOCK SIZE LXI H,SECTSZ SHLD FBLKS CALL AFBLK ALLOCATE INDEX BLOCK SHLD FINDX SAVE ITS ADDRESS POP H SHLD FBLKS RESTORE BLOCK SIZE * * NOW READ THROUGH THE FILE AND NOTE THE ADDRESS * OF EACH BLOCK IN THE INDEX * RND20 MVI A,250 STA RNCNT 250 MAX * * DO NEXT BLOCK * RND30 LHLD FCURSC XCHG LHLD RNPTR MOV M,E STORE CURENT SECTOR ADDRESS INX H MOV M,D INTO MAP INX H SHLD RNPTR UPDATE MAP POINTER LDA RNCNT DCR A DECREMENT COUNT STA RNCNT JZ RND35 DONE 128, MOVE TO EOF * * MOVE TO NEXT BLOCK * CALL DDRNB JMP RND40 EOF, DONE JMP RND30 * * * SPACE UNTIL EOF * RND35 CALL DDRNB JMP RND40 EOF JMP RND35 MOVE TO NEXT BLOCK * * NOW WRITE OUT MAP...ID IS SET IN TFID.,SO IS UNIT * RND40 SHLD FBDL SHLD FNBD SET AT EOF LHLD FINDX SHLD TDAD LXI H,DIBUF SHLD TBUF LXI H,SECTSZ GET STANDARD SECTOR SIZE SHLD TBCNT CALL WDSK * * UPDATE INDEX SAVED IN MEMORY, IF ANY * CALL UPIM * * UPDATE DIRECTORY INDEX POINTER * LHLD FID CALL SDIRX SEARCH FOR FILE LHLD DBUF POINTS TO ENTRY FOR FILE LXI D,DEINX-DEBUF DAD D XCHG LHLD FINDX PUT IN INDEX ADDRESS MOV A,L STAX D INX D LOW MOV A,H STAX D HIGH CALL WDSK REWRITE DIRCTORY * * THATS IT * CALL RBUF RELEASE BUFFER JMP NRET * * RNER0 CALL ERRL1 DEVICE FILE RANDOM OPERATION DB RERR0 * ********************* * * * UPDATE INDEX POINTED TO BY FAIND, IF ANY * MAKE A COPY OF DIBUF INTO IT * UPIM LHLD FAIND INX H FAIND = -1 IF NONE MOV A,H ORA L RZ . NONE TO DO DCX H -> MEMORY COPY OF INDEX LXI D,DIBUF -> MASTER COPY LXI B,SECTSZ CALL MOVEV MOVE IT RET . SIMPLE, NO? * PAGE * * ******************************************* * * * * ABORT OPERATION * * * TYPE ERR FOLLOWED BY THE CONTENTS OF USER A, * USER B, AND USER HL. * * RETURN TO THE SYSTEM THROUGH SRESET. * * ABURP CALL OUST TYPE CR LF ERR DB CR DB LF ASC 'ERR: ' DB 0 LDA UA CALL OUT8B TYPE A LDA UB CALL OUT8B TYPE B CALL O16N TYPE HL DW UHL JMP SRESET RETURN THRU SRESET * ********************* * * * PRINT THE 16 BIT NUMBER POINTER TO BY CALL+1, * PRECEEDED BY A BLANK. * RETURN PAST THE POINTER * O16N MVI A,BLNK CALL CONOUT POP H -> POINTER MOV E,M INX H MOV D,M DE = POINTER INX H PUSH H UPDATE RETURN XCHG MOV E,M INX H MOV D,M XCHG . = NUMBER * FALL INTO OUT16 * * OUTPUT THE 16 BIT NUMBER IN HL * OUT16 MOV A,H CALL OUT8 MOV A,L * * OUTPUT 8 BIT NUMBER * OUT8 MOV C,A RAR RAR . OVER IT GOES RAR RAR CALL OUT8A MOV A,C * * OUT8A ANI 15 ADI 48 CPI 58 JC CONOUT IT WAS A NUMBER, OUTPUT IT AND RETURN ADI 7 JMP CONOUT * * * OUTPUT A 8 BIT NUMBER FOLLOWED BY A BLANK * OUT8B CALL OUT8 MVI A,BLNK NOW THE SPACE JMP CONOUT OUTPUT IT AND RETURN * * * OUTPUT ASCII MESSAGE FOLLOWING CALL TO ZERO BYTE * OUST POP H OUST5 MOV A,M FETCH CHAR INX H ORA A JZ OUST9 ZERO BYTE, RETURN CALL CONOUT TYPE CHAR JMP OUST5 * OUST9 PCHL * PAGE * * ******************************************* * * * * SET UNIT OPERATION * * UA HAS THE DESIRED UNIT NUMBER * * ERRORS: * ILLEGAL UNIT NUMBER * * SUNH LDA UA LXI H,MAXUN POINT TO MAXIMUM UNIT NUMBER CMP M JNC SUNER YES, IT IS ILLEGAL STA DUNIT NO, SET UNIT,DEFAULT JMP NRET * * SUNER CALL ERRL1 DB UNER0 ILLEGAL UNIT * PAGE * * ******************************************* * * * * * FILE CONTROL STATUS CHECK * * UA HAS THE FILE NUMBER * FCTRL CALL PFCB PREPARE LHLD UDE LOAD A, DE, HL XCHG LHLD UHL LDA UB CALL DVBR CALL DRIVER DB DTCTL * SHLD UHL SAVE REGISTERS XCHG . FOR SHLD UDE RETURN STA UA JMP NRET * ********************* * * * ALLOCATE BUFFER * * DE HAS DESIRED SIZE * CALL ALBUF * RETURN HL HAS THE BUFFER * * MINAD-DE IS USED, MINAD IS UPDATED * ABORT EXIT IF NO SPACE * ALBUF LHLD MINAD GET LOWEST ADDRESS IN USE CALL ARITH HL=HL-DE XCHG SHLD WBUFSZ SAVE SIZE FOR ERROR DEALLOCATION LHLD LOWAD GET LOWEST ALLOWED ADDRESS CALL COMP PASSING MIN ADDR? JC ALB9 NEW MIN LT LOWAD, MEM OVERFLOW XCHG SHLD MINAD SHLD WBUFAD SAVE FOR ERROR DEALLOCATION RET * * * ABORT, NO SPACE IS AVAILABLE * ALB9 LXI H,0 SHLD WBUFSZ CLEAR TO AVOID SCREW-UPS CALL ERRL1 DB MER0 * ********************* * * * COMPARE DE AND HL * * DE,HL ARE UNCHANGED * * CARRY IF HL > DE UNSIGNED * ZERO IF HL = DE * COMP MOV A,D SUB H RC RNZ MOV A,E SUB L RET . SIGN AND ZERO SET * ********************* * * * PROTECTION TEST (PROTEST) * * CURRENT FCB IS SET * CALL PROTST * BIT(S) TO TEST * RETURN, NO (NONZERO RESULT) * RETURN, OK (ZERO RESULT) * * PROTST POP H GET RETURN ADDRESS, POINTER TO PROTECTION LDA FPROT GET FILE ATTRIBUTES ANA M MASK AND TEST INX H MOVE PAST TEST WORD JZ RP3 OK...RETURN PAST IT PCHL . RETURN, PROTECTION SET * * * ********************* * * * MOVE MEMORY ROUTINES * * DE HAS SOU ADDRESS, HL HAS DEST ADDRESS * CALL MOVEF * MOVE COUNT * RETURN * * MOVEF XTHL . GET RETURN ADDRESS MOV C,M IT POINTED TO THE COUNT INX H MOVE UP RETURN XTHL . PUT IT BACK XRA A MOV B,A BC HAS COUNT JMP MOVEA * ********************* * * * MOVE VARIABLE SIZE BLOCK * * BC HAS COUNT, DE HAS SOURCE, HL HAS DESTINATION * CALL MOVEV * RETURN * MOVV1 LDAX D MOV M,A INX H BUMP POINTERS INX D DCX B MOVEV MOV A,B MOVEA ORA C JNZ MOVV1 RET * ********************* * * * * PREPARE FCB * * UA HAS FCB NUMBER * CALL PFCB * RETURN FCB FRADD SET * ABORT IF ILLEGAL FCB NUMBER * * PFCB LDA NFCB GET NUMBER OF FCB'S MOV B,A LDA UA GET FILE NUMBER DESIRED CMP B JNC PFC90 ERROR, TOO BIG * LHLD FCBASE BOTTOM OF FCB'S LXI D,LNFCB LENGTH OF EACH ONE ORA A JZ PFC6 FILE "0" NO ADDING NEEDED * PFC5 DAD D MOVE TO NEXT FCB DCR A JNZ PFC5 * * * SPECIAL ENTRY POINT FOR CLOSE ALL OPERATION * * ENTER WITH HL--> FCB * PFC6 SHLD FRADD SAVE THE FCB ADDRESS XCHG LXI H,FCBORG MAKE A COPY TO FCBORG CALL MOVEF MOVE IT DB LNFCB * * CHECK IF UNOCCUPIED * LHLD FID MOV A,H ORA L RNZ . NON ZERO ID, OK * PFC90 CALL ERRL1 ERROR DB ERUFN * ********************* * * * IF BUFFER IS DYNAMIC RELEASE IT * * CURRENT FCB IS SET * CALL RBUF * RETURN * RBUF LHLD FBUFA INX H MOV A,H ORA L RNZ . FILE IS NOT UNBUFFERED * * RELEASE BUFFER * CALL WDBUF WRITE DIRTY BUFFER LHLD FBLKS XCHG . DE HAS SIZE LHLD TBUFA HL HAS ADDRESS CALL DLBUF DEALLOCATE LXI H,0 SHLD TBUFA ZERO BUFFER POINTER RET * ********************* * * * NAMIN, PROCESS IN A NAME * * HL POINTS TO NAME * CALL NAMIN * * NAME IS ASSEMBLED INTO DEBUF * FUNIT IS SET * * FIRST ZERO OUT NMLEN BYTES * NAMIN LXI D,DEBUF MVI B,NMLEN XRA A * NAM05 STAX D INX D DCR B JNZ NAM05 LXI D,DEBUF PUT IT HERE MVI B,NMLEN+1 MAXCOUNT+1 * * * LOOP HERE WITH: DE--> NEXT CHARACTER POSITION * B = NUMBER OF CHARACTERS REMAINING * HL--> NEXT INPUT CHARACTER * NAM10 MOV A,M PICKUP A CHAR CALL NAMTST JZ ICIN ERROR!! * * FALL THROUGH WITH LEGAL CHAR IN 'A' * NAM20 STAX D INX H INX D DCR B JNZ NAM10 * * ERROR--TOO MANY CHARACTERS * CALL ERRL1 DB ERNTL NAME TOO LONG * * * ZERO BYTE FOUND (NAMTST COMES HERE) * NAM30 POP B GET RID OF RET LDA DUNIT USE DEFAULT UNIT NAM31 STA FUNIT AS FILE UNIT LDA DEBUF CHECK FOR NULL NAME ORA A RNZ . IF OK * ICIN CALL ERRL1 DB ERINM ILLEGAL NAME * * * FOUND UNIT, PICK IT UP * NAM40 POP B INX H MOV A,M PICKUP CHAR ANI 127 SBI '0' SUBTRACT ZERO CHR JC ICIU BAD CHAR LXI H,MAXUN CHECK RANGE OF UNIT NUMBER CMP M JC NAM31 OK, SELECT IT * ICIU CALL ERRL1 DB ERICU UNIT ERROR * ********************* * * * TEST A NAME CHARACTER IN "A" * * RETURN IF NONSPECIAL LEGAL CHARACTER * ERROR IF ILLEGAL CHARACTER * * GO TO NAM30 OR NAM40 IF TERMINATOR FOUND * (RETURN DISPOSED OF) * NAMTST ANI 127 MASK DOWN JZ NAM30 END OF NAME CPI '/' SLASH? JZ NAM40 SELECT UNIT CALL DLTST CHECK FOR BAD CHARS RZ . IF SO * CPI '#' THE OTHER ONES RZ . BAD CPI ' '+1 SPACE JC ICIN CONTROL CHAR OR SPACE CPI 127 NOT .EQ. OR .GT. RET . LEGAL CHAR * PAGE * * ********************* * * * * SEARCH DIRECTORY * * * HL POINTS TO NAME, CURRENT DIREC SET ( ??? ) * * CALL SDIR * RETURN = NOT FOUND, DFC=BLOCK WITH ROOM OR 0 IF DIR FULL * RETURN = FOUND, DBUF POINTS TO ENTRY * SDIR CALL NAMIN PROCESS NAME XRA A STA DRID SET ID TO ZERO STA DRID+1 * * ALTERNATE ENTRY FROM SDIRX * COME HERE WITH A=0,DRID EQU FILE ID * SDI02 STA DFC INITIALIZE STA DFC+1 FREE POINTER * * READ FIRST SECTOR * LXI D,DDSC LXI H,TDAD CALL MOVEF SET TRANSFER DESCRIPTOR DB TBUF-TDAD+2 LDA FUNIT STA TUNIT DISK UNIT * READ SDI07 CALL RDSK * * SEE ABOUT FREE STUFF * LHLD DFC MOV A,L ORA H JNZ SDI20 ALREADY FOUND ONE LDA DINE CPI DREMS JNC SDI20 SECTOR IS FULL LHLD TDAD SHLD DFC SAVE AVAILABLE SECTOR * * SET UP DIRECTORY SECTOR SEARCH * SDI20 LXI H,DRFDS FIRST ENTRY ADDRESS SHLD DBUF SAVE POINTER LDA DINE STA DCNT SAVE COUNT ORA A JZ SDI70 SECTOR IS EMPTY, MOVE TO NEXT * * LOOP AND TEST ENTRIES * SDI30 LHLD DRID MOV A,L ORA H JNZ SDI50 ITS A SEARCH BY ID * * TEST NAME * LXI D,DEBUF USER NAME LHLD DBUF NAME IN SECTOR * * COMPARE STRINGS * MVI B,NMLEN SDI40 LDAX D CMP M JZ SDI44 MATHC ON THIS CHARACTER * * TRY TO MATCH UPPER/LOWER CASE CHARACTERS * CPI 97 ="a" JC SDI42 DEBUF CHARACTER NOT LOWER CASE SBI 32 DEBUF CHAR WAS LC, UPSHIFT AND TRY JMP SDI43 TO MATCH AGAIN * * DEBUF CHAR NOT LC, TRY TO UPSHIFT DIREC CHAR * SDI42 MOV A,M CPI 97 ="a" JC SDI60 DIREC CHAR NOT LC, NO MATCH LDAX D GET DEBUG CHAR ADI 32 DOWNSHIFT DEBUG CHAR TO TRY MATCH * * TRY ALTERNATE MATCH * SDI43 CMP M JNZ SDI60 NO, SECOND MATCH ATTEMPT FAILED * SDI44 INX D MATCH INX H DCR B MOVE TO NEXT CHARACTER JNZ SDI40 * * MATCH * SDI45 LHLD DBUF MOVE ENTRY INTO XCHG LXI H,DEBUF DEBUF CALL MOVEF DB DRESZ JMP RP2 RETURN TO CALL PLUS 2 * * * MOVE TO NEXT ENTRY * SDI60 LDA DCNT DCR A COUNT DOWN JZ SDI70 SECTOR EMPTY STA DCNT LHLD DBUF LXI D,DRESZ MOVE POINTER DAD D SHLD DBUF JMP SDI30 * * * MOVE TO NEXT SECTOR * SDI70 LHLD IHFOR FORE POINTER MOV A,H ORA A RM . EOF, FAIL SHLD TDAD SET NEXT BLOCK JMP SDI07 * * * CHECK FILE ID, NOT NAME * SDI50 LHLD DBUF LXI D,DEFID-DEBUF DAD D HL POINT TO ID LDA DRID CMP M JNZ SDI60 NOT SAME INX H LDA DRID+1 CMP M JNZ SDI60 NOPE JMP SDI45 YES, MATCH * ********************* * * * SEARCH DIRECTORY BY ID * * SAME AS SDIR BUT HL HAVE ID * ENTER AT SDIRY WITH A = UNIT#, ALSO * * THE FILE MUST EXIST. THE DIRECTORY ON WHICH THE * FILE EXISTS IS SEARCHED. * SDIRY STA FUNIT SPECIAL ENTRY FOR "OPEN?" SDIRX SHLD DRID SAVE ID XRA A SET A TO ZERO CALL SDI02 GO SEARCH CALL CI98 FILE MUST EXIST, OR ELSE! RET * ********************* * * * DIRECTORY FILE DESCRIPTOR * DDSC DW DIRDB READ OPCODE DDSC2 DW SECTSZ DW IDDIR DW DIBUF * ********************* * * * MAKE ENTRY IN DIRECTORY * * DEBUF HAS ENTRY, DFC IS SET * EDIR LHLD DFC MOV A,L ORA H CZ CI98 BETTER NOT BE FULL! * * READ SECTOR WITH FREE ENTRY * EDI10 SHLD TDAD SAVE DISK ADDRESS LXI D,DDSC2 LXI H,TBCNT CALL MOVEF DB TBUF-TBCNT+2 LDA FUNIT STA TUNIT UNIT CALL RDSK READ SECTOR * * MOVE IN ENTRY * LXI D,DIBUF LHLD DIND HL = NEXT DISPLACEMENT DAD D HL = DESTINATION LXI D,DEBUF DE = ENTRY BUFFER CALL MOVEF DB DRESZ * * UPDATE HEADER * LXI H,DINE INR M NUMBER OF ENTRIES LHLD DIND LXI D,DRESZ DAD D SHLD DIND NEXT ENTRY DISPLACEMENT CALL WDSK RE WRITE THE ENTRY RET . THATS ALL * ********************* * * * REMOVE DIRECTORY ENTRY * * DIBUF HAS SECTOR * DBUF POINTS TO ENTRY * ALWAYS NORMAL RETURN * RDIR LXI H,DINE DCR M UPDATE COUNT JZ RDI60 IT IS NOW ZERO, NOTHING TO MOVE * * CALCULATE NUMBER OF WORDS TO MOVE * * LXI D,DIBUF LHLD DIND DAD D HL=ADDR OF NEXT FREE DIR ENTRY LXI D,-DRESZ DAD D SUBTRACT ONE ENTRY XCHG LHLD DBUF MOV A,E CALCULATE BC=DE-HL =NO.OF BYTES TO BE MOVED SUB L MOV C,A MOV A,D SBB H MOV B,A ORA C JZ RDI60 NOTHING TO MOVE LXI D,DRESZ PUSH H SAVE DBUF FOR DESTINATION DAD D = SOURCE ADDRESS (DBUF+DRESZ) XCHG . PUT IN DE POP H = DESTINATION ADDRESS (DBUF) CALL MOVEV RECALL THAT BC HAS COUNT * RDI60 LHLD DIND LXI D,-DRESZ UPDATE NEXT ENTRY DISPLACEMENT DAD D SHLD DIND CALL WDSK TDAD STILL IS SET, REWRITE RET * ********************* * * * GET FILE ID * * CURRENT LOGICAL UNIT DESCRIPTOR IS SET UP * CALL GFID * RET WITH ID IN DE * ABORT IF NO IDS ARE AVAILABLE * * SET UP READ * GFID LXI D,NIDD LXI H,TDAD CALL MOVEF SET TRANSFER DESCRIPTOR DB TBUF-TDAD+2 LDA FUNIT STA TUNIT UNIT. CALL RDSK READ IT * LHLD IDBUF PUSH H SAVE ID INX H INCREMENT MOV A,H ORA L JZ NOIDS NO IDS LEFT, SERIOUS SHLD IDBUF OK, REWRITE CALL WDSK POP D PUT ID INTO DE RET * * NOIDS POP D GET RID OF IT CALL ERRL0 DB ERNID NO IDS LEFT * ********************* * * * FSM DESCRIPTOR * NIDD DW DANIB BLOCK # DW NIDBC BYTE COUNT DW IDNID FILE ID DW IDBUF BUFFER * ********************* * * * WRITE BUFFER TO DEVICE IF DIRTY * WDBUF LDA FFLAG ORA A TEST DIRTY FLAG RZ . NOT DIRTY * LHLD FBDL THE LAST BYTE IN THE BUFFER XCHG LHLD TBUFA SET HL=START ADDRESS, DE=LAST ADDRESS CALL DVBR WRITE BLOCK DB DTWB JMP SEOF EOF, ERROR JMP WDB50 * ********************* * * * READ NEXT BUFFER LOAD FROM DEVICE * * CLEAN BUFFERS, READ BLOCK, THEN SET NBD=0, * AND BDL=INCOMING BLOCK SIZE * COME WITH HL=BUFFER SIZE * RDNB PUSH H CALL WDBUF CLEAN IF DIRTY POP D LHLD TBUFA CALL DVBR READ NEXT DB DTRNB RET . EOF ENCOUNTERED NOP NOP SHLD FBDL SET BDL LXI H,0 SHLD FNBD NBD=0 JMP RP2 RETURN CALL +2 * ********************* * * * WRITE CURRENT BUFFER AND LOAD NEXT * * CALL WITH SIZE IN HL * SET NBD=0, BDL FROM DRIVER, FFLAG=0 * WDBR XCHG LHLD TBUFA CALL DVBR WRITE DB DTWBR JMP SEOF EOF, ERROR * WDB45 SHLD FBDL SET BDL LXI H,0 SHLD FNBD NBD=0 * WDB50 XRA A STA FFLAG FFLAG=0 RET . RETURN * ********************* * * * DEVICE DRIVER BRANCH * * CALL WITH CALL+1=OPERATION * PASS DE, HL, AND A TO THE DRIVER * DVBR XTHL MOV C,M PICKUP DISPLACEMENT INX H MOVE PAST IT MVI B,0 BC=DISPLACEMENT XTHL . SAVE UPDATED RETURN PUSH H LHLD FDRIV DAD B HL->DISPATCH ADDRESS MOV B,A MOV A,M PICKUP FIRST PART INX H MOV H,M THEN SECOND MOV L,A HL=DISPATCH ADDRESS ORA H JZ IDAC NO ZERO OPERATION.. ERROR MOV A,B XTHL . RESTORE HL, RET . THEN GO INTO DRIVER. * ********************* * * * DISK DRIVER READ LAST BLOCK * DDRLB LHLD FBACK GET BACK POINTER MOV A,H TEST FOR BOF ORA A RM . YES, WE'RE ALL THE WAY BACK SHLD FCURSC SET AS CURRENT SECTOR AND FALL THROUGH * * * * DISK DRIVER READ BLOCK * DDRBL CALL RBLK RX2 XTHL . RETURN CALL+2, BUT INX H LEAVE INX H HL INX H ALONE. XTHL RET * * * PAGE * * ********************* * * * * DISK DRIVER CONTROL/STATUS OPERATION * * COME HERE WITH A, DE, HL SET FROM USER CALL B,DE,HL * DDCTL ORA A JZ DDC2 IF STATUS REQUEST * * CPI 7 JZ CTRL7 RETURN STATUS * * CPI 8 JZ CTRL8 SET DRIVE READY TRAP CPI 9 JZ CTRL9 READ BUFFER CPI 10 JZ CTR10 WRITE BUFFER * CPI 4 IS IT A "LOAD INDEX" REQUEST? JZ DDC4 YES * CALL ERRL2 NO, BUT THAT'S ALL WE DO DB ERNCT * CTRL7 EQU $ * <============ NEED TO LOOK INTO THIS ROUTINE ===== * LHLD FNBD GET CURRENT BYTE DISPLACEMENT XCHG LHLD FBLKS AND THE BLOCK SIZE CALL ARITH HL = HL - DE XCHG . RETURN IT IN DE MVI A,-1 SAY DRIVE READY FOR NOW <============= RET * * * * SET DRIVE NOT READY TRAP * CTRL8 SHLD DSKRD SET IT RET . QUICK CALL * * * REFRESH BUFFER OF STATIC BUFFERED FILE * CTRL9 CALL BUFTST TEST TYPE OF BUFFERING RZ . IF DYNAMIC BUFFER JMP RBLK READ THE BLOCK AGAIN AND RETURN * * * WRITE OUT THE BUFFER IF STATIC BUFFERED * CTR10 CALL BUFTST TEST TYPE OF BUFFERING RZ XRA A STA FFLAG CLEAR THE BUFFER DIRTY FLAG JMP WBLK WRITE IT OUT AND RETURN * * * * RETURN FILE STATUS * DDC2 LDA FPROT A = FILE PROTECTION MVI D,0 NOTHING ELSE OF IMPORTANCE! RET * * * LOAD INDEX INTO ADDRESS IN HL * DDC4 INX H TEST FOR -1 FIRST MOV A,H ORA L DCX H JZ DDC4A IT IS -1, SKIP TEST * LXI D,SECTSZ CHECK FOR OVERWRITE CALL MEMCHK MVI A,1 ORA A SET NZ TO FORCE CALL * DDC4A LHLD UHL WE KNOW WHERE IT IS SHLD FAIND ALL IS WELL, SET IT IN CNZ RINDY LOAD THE INDEX RET * PAGE * * ********************* * * * * DISK DRIVER WRITE BLOCK * DDWBL CALL WBLK WRITE IT JMP RX2 AND RETURN * * * * DISK DRIVER WRITE BLOCK/READ NEXT * DDWBR CALL WBLK WRITE OUT CALL DDRNB READ NEXT CALL LNKBLK NONE SO ADD ONE JMP RX2 WASN'T THAT EASY * * NOTE: THE ABOVE ROUTINE IS REALLY ESTHETICALLY * PLEASING. (IF I DO SAY SO MYSELF.) * ********************* * * * WRITE BLOCK OF DISK FILE * * WRITE THE CURRENT BLOCK OF THE CURRENT FILE. * IF THIS BLOCK HAS THE EOF, UPDATE THE HEADER. * * INFORMATION IN THE CURRENT FCB IS USED. * * * UPDATE HEADER IF NECESSARY * WBLK LDA FFORE+1 HIGH ORDER FORE ORA A JP WBL60 NO EOF, JUST WRITE LHLD FBDL MOV A,H ORI 128 SET HIGH BIT MOV H,A SHLD FFORE SET NEW COUNT IN FORE PTR * * SET OUTGOING HEADER * LXI D,FFORE LXI H,OHFOR CALL MOVEF JUST MOVE IT DB OHPRO-OHFOR+1 CALL STDAD SET TRANSFER DESCRIPTOR JMP WDSKH WRITE BLOCK AND HEADER * * * WRITE BLOCK TO DISK OR OTHER WONDERFUL DEVICE * WBL60 CALL STDAD SET TRANSFER DESCRIPTOR JMP WDSK WRITE IT OUT * ********************* * * * SET TRANSFER DESCRIPTOR * * COPY STUFF FROM FCB TO TDAD * STDAD LHLD FCURSC SHLD TDAD DISK ADDRESS LHLD FBLKS SHLD TBCNT BYTE COUNT LHLD FID SHLD TFID FILE ID LHLD TBUFA SHLD TBUF BUFFER ADDRESS LDA FUNIT STA TUNIT DISK UNIT RET * ********************* * * * READ NEXT BLOCK OF A DISK FILE * * CURRENT FCB HAS HEADER, ID, ETC. * CALL DDRNB * RETURN - EOF * RETURN - OK, HEADER, FCB UPDATED * * * TEST FOR EOF * DDRNB LHLD FFORE MOV A,H ANI 127 CMP H IS A=H=127? MOV H,A HAVE HL=COUNT IN CASE RNZ . A AND H DIFFER BY HIGH BIT, => EOF * XCHG . DE HAS NEXT SECTOR ADDRESS LHLD FCURSC SHLD LSECT SAVE CURRENT SECTOR ADDRESS XCHG SHLD FCURSC SET CURRENT AS NEXT CALL RBLK READ BLOCK PUSH H SAVE BDL * * PERFORM STRUCTURE TEST * LXI H,LSECT POINT TO LAST SECTOR ADDRESS LDA FBACK CMP M COMPARE LOW ORDER JNZ FSBAD BAD BAD BAD INX H LDA FBACK+1 CMP M COMPARE HIGH ORDER JNZ FSBAD BAD BAD BAD POP H PASS BACK BDL JMP RX2 * * FSBAD CALL ERRL0 SERIOUS ERROR DB FBER FILE STRUCTURE BAD * ********************* * * * * READ DISK BLOCK * * CURRENT FCB IS SET * CALL RBLK * RETURN * * RBLK CALL STDAD SET TRANSFER DESCRIPTOR CALL RDSK READ IT * * COME HERE AFTER TRANSFER * RBL30 LXI D,IHFOR COPY HEADER TO LXI H,FFORE FCB. CALL MOVEF DB FPRST-FFORE+1 * * IF EOF, RETURN COUNT, ELSE BLOCK SIZE * LHLD FFORE MOV A,H ORA A TEST HIGH BIT FOR EOF JP RBL40 NO EOF ANI 127 MASK OFF HIGH BIT MOV H,A HL HAVE NEW COUNT RET . RETURN * RBL40 LHLD FBLKS NO EOF, USE BLOCK SIZE RET * ********************* * * * FLUSH DEVICE BUFFER * FDB LHLD FDRIV LXI D,DTITO DISPL. TO ITO DAD D MOV A,M PICK UP ITO ORA A RZ . ZERO, RETURN CALL WDBUF WRITE OUT (IT BETTER BE DIRTY) LXI H,0 THEN BDL=NBD=0 JMP WDB45 * PAGE * * ********************* * * * * RELEASE FILE BLOCK * * CURRENT FCB HAS STUFF * CALL RFBLK * RETURN * * FCURSC IS THE BLOCK RELEASED. * THE FREE SPACE MAP IS UPDATED. * FDLTA IS UPDATED * * GET COUNT OF TRUE NUMBER OF SECTORS * RFBLK LDA FPRST ANI 7 EXTRACT LOW 3 BITS STA RFBCN STA RFBC1 SAVE * * REWRITE BLOCK * SET OUTPUT HEADER, THEN LOOP AND WRITE * LXI H,0 SHLD OHFOR SHLD OHBAK SHLD OHFID SHLD TFID MVI A,1 STA OHPRO 1 SECTOR LHLD FCURSC SHLD TDAD SET DISK ADDRESS LXI H,SECTSZ SHLD TBCNT SET STANDARD BYTE COUNT LXI H,DKBUF SHLD TBUF SET TO USE DISK ALLOC. BUFFER LDA FUNIT STA TUNIT SET UNIT * RFB10 CALL WDSKH WRITE SECTOR AND HEADER LHLD TDAD INX H MOVE TO NEXT SECTOR SHLD TDAD LXI H,RFBCN DCR M COUNT DOWN ON SECTOR COUNT JNZ RFB10 * * READ FREE MAP * LXI D,MAPDS LXI H,TDAD CALL MOVEF MOVE STUFF TO TRANSFER DESCRIPTOR DB TBUF-TDAD+2 CALL RDSK * * FIND WORD TO UPDATE * LHLD FCURSC BLOCK NUMBER DAD H DAD H DAD H DAD H DAD H *32/256 = /8 MOV L,H MVI H,0 HL HAS TRACK NO. LXI D,DKBUF DAD D HL POINTS TO ENTRY * * UNPACK IT * PUSH H SAVE HL MOV B,M CALL UNPK UNPACK INTO PBUF * * SET BITS * LXI D,TMBUF TRACK MAP BUFFER LDA FCURSC ANI 7 MOV L,A MVI H,0 HL HAVE SECTOR ADDRESS DAD D HL NOW POINT TO WORD LDA RFBC1 GET COUNT OF SECTORS * RFB30 MVI M,1 SET BIT INX H DCR A JNZ RFB30 CALL PACK RE PACK THE WORD POP H MOV M,B STORE BACK INTO MAP * * REWRITE MAP * CALL WDSK LHLD FDLTA DCX H SHLD FDLTA RET . THAT IS ALL * ********************* * * * FREE SPACE MAP DESCRIPTOR * MAPDS DW DAFSB DW 80 MAP LENGTH DW IDFSM MAP ID DW DKBUF USE DISK ALLOCATION BUFFER * ********************* * * * UNPACK B INTO TMBUF * 1 BIT IS PLACED IN EACH WORD. * * UNPK LXI H,TMBUF MVI D,8 ZERO IT FIRST XRA A = 0 * UNPK5 MOV M,A INX H DCR D JNZ UNPK5 * LXI H,TMBUF MOV A,B * * UNPACK A INTO HL * UNP ORA A RZ . ZERO, DONE RAL . LEFT 1 PLACE, ZERO FILL MVI M,0 JNC UNP10 NO CARRY, ITS ZERO INR M INCREMENT TO 1 UNP10 INX H JMP UNP * * * PACK TMBUF INTO B, RETURNS B * * PACK LXI H,TMBUF * PACK HL INTO B * PAC XRA A MVI D,8 COUNT IS 8 * PAC5 MOV E,A SAVE PARTIAL MOV A,M GET BIT RAR . PUT IN CARRY MOV A,E GET PARTIAL RAL . SHIFT IN BIT INX H DCR D JNZ PAC5 AGAIN MOV B,A RET . QUIT * ********************* * * * PREPARE BUFFER * * CURRENT FCB IS SET UP * CALL PBUF * RETURN - BUFFER IS SET UP * PBUF CALL BUFTST RNZ . ALL DONE IF BUFFERED * * UNBUFFERED, ALLOCATE AND PRIME BUFFER * PBU70 LHLD FBLKS PUSH H SAVE BLOCK SIZE XCHG CALL ALBUF ALLOCATE BUFFER SHLD TBUFA OK POP D DE=CT, HL->BUFFER CALL DVBR READ IN BLOCK DB DTRB JMP SEOF BAD IDEA ******* SHLD FBDL RET * * * TEST IF FILE IS UNBUFFERED * BUFTST LHLD FBUFA INX H MOV A,H ORA L IF IT WAS -1, IT IS UNBUFFERED DCX H BACK TO TRUE SHLD TBUFA SET IT TO TRUE BUFFERED ADDRESS RET . ZERO PSW IF UNBUFFERED * ********************* * * * RESTORE FCB * * IF FRADD ZERO, DO NOTHING. LEAVE FRADD ZERO. * RFCB LHLD FRADD MOV A,L ORA H RZ . ZERO, JUST RETURN LXI D,FCBORG CALL MOVEF MOVE BACK DB LNFCB * RFCB1 LXI H,0 SHLD FRADD SET FRADD TO ZERO RET * ********************* * * * LINK BLOCK * * ALLOCATE AND LINK A BLOCK ONTO THE CURRENT ONE. * FOR DISK FILES ONLY. * LNKBLK CALL PROTST CHECK IF ALLOCATE PROTECTED DB PALO JMP EOFE0 YES, PROTECTED! * LHLD FBACK SHLD LNKT2 SAVE BACK POINTER * * SET UP HEADER FOR NEW BLOCK * LHLD FCURSC SHLD FBACK SET BACK AS CURRENT SHLD LNKT1 SAVE CURRENT LXI H,EOFCD SHLD FFORE SET FORE = EOF * * ID, ETC. ARE THE SAME, ALLOCATE NEW * CALL AFBLK SHLD FCURSC SET AS CURRENT SECTOR * * UPDATE HEADER OF LAST BLOCK * SHLD OHFOR FORE IS NEW SECTOR LHLD LNKT1 SHLD TDAD DISK ADDRESS OF LAST BLOCK LHLD LNKT2 SHLD OHBAK RESTORE BACK POINTER CALL WDSKH LHLD FINDX INDEXED? MOV A,H ORA L JZ LNK40 NO, FORGET IT * * UPDATE RANDOM FILE INDEX * CALL RINDX READ INDEX MVI B,250 LXI H,DIBUF * * SEARCH FOR ZERO ENTRY * LNK10 MOV A,M INX H ORA M JNZ LNK30 XCHG LHLD FCURSC GET CURRENT BLOCK XCHG MOV M,D PUT IN NEW ENTRY DCX H MOV M,E CALL WDSK WRITE OUT INDEX CALL UPIM UPDATE INDEX IN MEMORY, IF ANY MVI B,1 SET FLAG THAT WE FOUND IT * LNK30 INX H DCR B JNZ LNK10 NOT YET LNK40 LXI H,0 NO BYTES YET RET * PAGE * * ********************* * * * SEARCH FILE CONTROL BLOCKS * * HL HAS FILE ID * FUNIT HAS UNIT * CALL SFCBS * * RETURN - >1 FOUND * RETURN - 1 FOUND * RETURN - 0 FOUND * SFCBS XCHG . DE HAS ID NOW XRA A STA SFCT1 INITIALIZE COUNT LHLD FCBASE HL POINT TO FCB LDA NFCB STA SFCT2 SET COUNT * SFC20 LXI B,FID-FCBORG DAD B HL POINT TO FILE ID MOV A,M GET LOW ORDER ID INX H CMP E CHECK JNZ SFC70 NO, MOVE TO NEXT * MOV A,M GET HIGH ORDER ID CMP D CHECK JNZ SFC70 NO, MOVE TO NEXT * * ID MATCH, CHECK UNIT * LXI B,FUNIT-FID-1 DAD B MOVE TO UNIT LDA FUNIT CMP M CHECK UNIT JNZ SFC40 NO, UNITS DIFFER * * FOUND * LDA SFCT1 COUNT UP INR A STA SFCT1 * SFC40 LXI B,FPRST-FUNIT+1 DAD B MOVE TO BEGINNING OF NEXT FCB JMP SFC75 * * SFC70 LXI B,FPRST-FID-1+1 DAD B MOVE TO NEXT FROM FID+1 * SFC75 LDA SFCT2 DCR A STA SFCT2 DROP COUNT JNZ SFC20 DO NEXT * * DONE, DO RETURN * LDA SFCT1 GET COUNT CPI 2 RNC . MORE THAN 2 POP H INX H INX H INX H PUSH H UPDATE RETURN ORA A SET FLAGS RNZ . MUST BE 1 INX H INX H INX H XTHL . UPDATE RETURN RET . AND RETURN FOR ZERO. * PAGE * * ********************* * * * GET RID OF DANGLING BUFFER * BECAUSE OF AN ERROR * RIDBF LHLD WBUFSZ MOV A,H ORA L RZ . NONE XCHG LHLD WBUFAD GET IT AND FALL THROUGH TO DEALLOCATE * * FALL THROUGH * ********************* * * * DEALLOCATE BUFFER * * HL POINTS TO BUFFER * DE HAS BUFFER SIZE * THE BUFFER MUST BE IN THE SYSTEM GLOBAL AREA. * CALL DLBUF * RETURN * DLBUF SHLD DABT1 SAVE BUFFER ADDRESS XCHG SHLD DABT2 SAVE BUFFER SIZE DAD D ADDRESS OF NEXT BUFFER (HL) PUSH H LXI H,0 SHLD WBUFSZ CLEAR SAVED BUF POP H * * BUFFER ADDRESS (DE) * * COMPRESS BUFFER SPACE * * DE POINTS TO ONE WORD HIGHER THAN BUFFER * HL POINTS ONE WORD HIGHER THAN NEXT LOWER BUFFER. * DAB10 PUSH H LHLD MINAD COMPARE DE WITH MINIMUM ADDRESS CALL COMP POP H RESTORE HL JZ DAB30 MOVE IS DONE * MOVE A BYTE DCX H DCX D LDAX D MOV M,A JMP DAB10 * * * ADJUST ANY AFFECTED ADDRESSES IN THE FCBS * DAB30 SHLD MINAD LHLD FCBASE LXI D,FBUFA-FCBORG DAD D PUSH H FIRST BUFFER ADDRESS LDA NFCB STA DABT3 * DAB40 MOV E,M INX H MOV D,M GET BUFFER ADDRESS FROM FCB LHLD LOWAD CALL COMP COMPARE WITH GLOBAL BASE JC DAB50 BELOW, MUST BE A USER BUFFER * LHLD DABT1 CALL COMP COMPARE WITH BUFFER ADDRESS JNC DAB50 ABOVE AFFECTED AREA * LHLD DABT2 GET DELTA DAD D = UPDATED BUFFER ADDRESS XCHG . IN DE POP H MOV M,E INX H MOV M,D PUT BACK INTO FCB DCX H PUSH H * * MOVE TO NEXT * DAB50 POP H GET POINTER TO BUFF +1 LXI D,LNFCB DELTA TO NEXT FCB DAD D LDA DABT3 CHECK COUNT DCR A RZ STA DABT3 PUSH H SAVE POINTER AGAIN JMP DAB40 * * PAGE * * ********************* * * * ALLOCATE FILE BLOCK * * THE CURRENT FCB HAS THE DESIRED BLOCK SIZE AND HEADER. * AN ABORT IS TAKEN IF THE BLOCK SIZE IS ILLEGAL OR * IF THE DISK IS TOO FULL. * * CONTROL RETURNS TO CALL+1 WITH THE BLOCK ADDRESS IN HL * AFBLK LHLD FBLKS FIRST CHECK FOR LEGAL BLOCK SIZE PUSH H MOV A,L ORA H IS IT ZERO? JZ AFB95 IF SO, ILLEGAL LXI D,-4084 DAD D >=4084? (8*512-12) JC AFB95 YES ILLEGAL POP H GET BACK BLOCK SIZE CALL AFCALC CALCULATE THE REQUIRED NUMBER OF SECTORS * AFB10 MOV A,C C HAS THE NUMBER OF SECTORS STA AFBT1 WE SAVE IT HERE * * READ THE FSMAP * LXI D,MAPDS FROM HERE LXI H,TDAD TO THE TRANSFER DESCRIPTOR CALL MOVEF SET UP DB TBUF-TDAD+2 LDA FUNIT GET WHICH UNIT STA TUNIT SET FOR DISK DRIVER CALL RDSK * * SET UP MAP SEARCH FOR FREE SPACE * LXI H,0 SHLD AFBT4 SET BLOCK NUMBER LXI H,DKBUF ALLOCATION MAP BUFFER SHLD AFBT3 SET TRACK MAP POINTER * * OUTER LOOP FOR ALLOCATION BEGINS HERE * LOOK FOR NEXT TRACK * AFB20 LHLD AFBT3 MOV B,M PICKUP MAP INX H SHLD AFBT3 SAVE UPDATED POINTER CALL UNPK UNPACK THE MAP * * A TRACK MAP IS NOW UNPACKED IN PBUF * AFBT1 HAS THE REQUIRED NUMBER OF SECTORS * SET UP FOR MAP SCAN * LDA AFBT1 NUMBER OF SECTORS REQUIRED MOV B,A CALCULATE NUMBER FOR LOOP MVI A,9 ITERATIONS = 8-AFTB1+1 SUB B MOV B,A B HAS LOOP COUNT LXI H,TMBUF SCAN STARTING POINT * * THE INNER LOOP TO SCAN THE MAP OF THE CURRENT * TRACK BEGINS HERE * AFB40 SHLD AFBT6 SAVE PBUF POINTER LDA AFBT1 MOV C,A NUMBER OF SECTORS REQUIRED * AFB50 MOV A,M ORA A JZ AFB70 NO, THIS BLOCK IS NO GOOD INX H BUMP POINTER DCR C COUNT DOWN JNZ AFB50 TRY NEXT SECTOR * * AT THIS POINT WE HAVE FOUND A BLOCK ON THE CURRENT * TRACK OF SUFFICIENT LENGTH. WE NOW PROCEED TO GIVE * IT TO THE USER. * * CLEAR BITS IN MAP * LHLD AFBT6 PBUF POINTER LDA AFBT1 SECTOR COUNT AFB60 MVI M,0 CLEAR BIT INX H MOVE TO NEXT DCR A JNZ AFB60 * * REPACK CURRENT TRACK MAP AND REWRITE TO DISK * CALL PACK LHLD AFBT3 GET UPDATED TRACK MAP POINTER DCX H MOV M,B STORE MAP BACK IN CALL WDSK WRITE MAP, TDAD IS STILL SET UP * * INITIALIZE BLOCK FOR USER * LHLD AFBT4 GET SECTOR NUMBER SHLD TDAD TO THE TRANSFER DESCRIPTOR * * SET OUTGOING HEADER AND TRANSFER DESCRIPTOR * LHLD FBLKS SHLD TBCNT BYTE COUNT LXI H,0 SHLD TFID SET FREE SPACE FILE ID LHLD TBUFA SHLD TBUF SET BUFFER ADDRESS * * UNIT IS ALREADY SET * LXI D,FFORE LXI H,OHFOR CALL MOVEF MOVE IN USER HEADER DB OHPRO-OHFOR+1 * * INITIALIZE DISK BLOCK * CALL WDSKH WRITE HEADER AND DATA * * RETURN DISK ADDRESS TO USER AND UPDATE DELTA * LHLD FDLTA INX H SHLD FDLTA LHLD TDAD RET * ********************* * * * CALCULATE NUMBER OF SECTORS REQUIRED * AFCALC MVI C,0 FOR STARTERS LXI D,-SECTSZ FIRST SECTOR IS THIS BIG * AFB05 DAD D SUBTRACT AMOUNT IN THIS SECTOR INR C BUMP THE SECTOR COUNT MOV A,H ORA A RM . RESULT NEGATIVE, GOT ENOUGH * ORA L ZERO IS GOOD ENOUGH, THOUGH RZ * LXI D,-FULSZ SUBSEQUENT SECTORS ARE THIS BIG JMP AFB05 * ********************* * * CAN'T ALLOCATE ONE HERE...MOVE TO NEXT * * AFB70 LHLD AFBT4 DCR B TOTAL ITERATIONS JZ AFB80 THIS TRACK IS FULL INX H BUMP SECTOR NUMBER SHLD AFBT4 LHLD AFBT6 MOVE PBUF POINTER INX H UP ONE JMP AFB40 AND LOOP * * * THIS TRACK IS TOO FULL, TRY NEXT TRACK * AFB80 MOV A,L HL HAS SECTOR # ORI 7 MOV L,A INX H NOW AT NEXT TRACK SHLD AFBT4 DAD H MOV A,H CPI 5 UP TO SECTOR 280H ? JC AFB20 STILL OK * * DISK IS FULL ABORT * LHLD LNKT1 GET BACK CURRENT SECTOR SHLD FCURSC LHLD LNKT2 AND BACK POINTER SHLD FBACK * CALL ERRL1 DB DAER0 DISK FULL * * AFB95 CALL ERRL1 DB DAER1 ILLEGAL BLOCK SIZE * PAGE * * **************************** * * * SHORT RESET AFTER ABORT * USRES XRA A STA UA SRESET XRA A STA CIFILE SET CIFILE TO 0 INR A STA COFILE INR A STA UTIL SET UTILITY FILE = 2 * * CLEAR COMMAND STRING * LHLD FCBASE LXI D,FNBD-FCBORG DAD D POINT TO NBD WORD IN FCB #0 MVI A,4 CLEAR FOUR BYTES * CSTRG MVI M,0 INX H DCR A JNZ CSTRG NBD=BDL=0 * LXI SP,CISTK USE CI STACK CALL INRST RESET THE DISK TRAPS SHLD CRTRAP CLEAR CI RETURN TRAP = -1 LDA UA ORA A JZ CI CAN'T EXPLAIN ZERO * * WAIT FOR A CHARACTER * CALL CONIN CPI CR JZ CI CR....DON'T EXPLAIN * * TYPE MESSAGE * LHLD UTOS GET USER RETURN INTO HL SPHL POP H = USER RETURN HOPEFULLY LXI SP,CISTK MVI A,-1 STA OPER ERRP8 SETS EOPR TO OPER JMP ERRP8 * * ********************* * SRE50 STA UA SAVE SYSTEM ERROR * * 1) SET ERCD TO UA (THE CALLED ERROR #) * 2) SET ERROR TRAPS * 3) DO UTILITY WILL "CALLED FROM" MSG * * TRAP HERE IF ERROR DURING EXPLAIN * XTRP CALL OUST DB CR DB LF ASC "CAN'T EXPLAIN" DB 0 JMP ABURP TRY TO ABORT AGAIN * * PAGE * * ******************************************* * * * * * COMMAND INTERPRETER * ********************* * * * SOME CHARACTERS * CR EQU 13 ASCII CR LF EQU 10 ASCII LF SEMI EQU 59 SEMICOLON COMMA EQU ',' SLASH EQU '/' NSIGN EQU '#' ZCHR EQU '0' ASTRC EQU '*' * ********************* * * * EOF ON INPUT FILE, IF CIFILE = 0 (CONSOLE), THEN * DO A CLOSE ALL, ELSE DO A SHORT RESET. * CIEIF LDA CIFILE ORA A CHECK FOR ZERO JNZ USRES NOT ZERO, DO A SHORT RESET TO MOVE THE CONSOLE MVI A,255 CLOSE ALL FILES CALL SYS DB CAOP JMP CIABT JMP USRES WHY NOT? * ********************* * * * "RETURN" ENTRY * * PROCESS NEXT COMMAND, IF ANY * IF NONE, RETYPE PROMPT * RETURN LXI SP,CISTK CALL INRST RESET INT TRAPS LHLD CRTRAP CHECK RETURN TRAP INX H IF =-1, NOTHING TO DO MOV A,H ORA L JZ CI50 NONE DCX H <> -1, JUMP TO ADDRESS PUSH H HERE WE GO LXI H,-1 SHLD CRTRAP CLEAR TRAP RET . GO TO TRAPPER * ********************* * * * SET ERROR TRAPS TO CI STANDARD AND RESET INT TRAPS * CIRST LXI H,0 SHLD AERR SHLD FERR DCX H SHLD EERR * * RESET BOTH INTERRUPT TRAPS * * RETURN HL=-1 * INRST LXI H,0 SHLD DSKRD SET DISKREADY TO 0 DCX H NOW FOR -1 SHLD BDSK1 SHLD BDSK2 RET . MUST RETURN WITH -1 * ********************* * * * ECHO CHARACTER TO CI LOG FILE * * COME WITH CHAR IN A, AND RETURN THAT WAY * CRECHO MVI A,CR ENTRY POINT TO ECHO A CARRIAGE RETURN * ECHOUT MOV B,A LDA ECFILE CALL WB WRITE IT OUT CALL CI98 PANIC!!! MOV A,B RET * ********************* * * * RETURN AND SET TRAP * * COME HERE WITH TRAP ADDRESS IN USER HL * RETRAP LHLD UHL * SET CRTRAP AND FALL INTO CI SHLD CRTRAP * ********************* * * * READ AND PROCESS A COMMAND * CI LXI SP,CISTK SETUP STACK * CI50 LXI H,CIMSG RESET PROMPT STRING SHLD TDPRO CALL CIRST * * EAT LEADING BLANKS AND ","'S * CI51 CALL CIBNK JZ CIEIF ZERO INDICATES EOF CALL CIBUP WASN'T " " OR ","... BACK UP 1 CHAR * * ECHO THE COMMAND * LDA SWECH RRC JNC CI59 NO ECHO LXI H,0 SHLD CECT SET COUNT TO ZERO * CI53 LDA ECFILE GET ECHO FILE NUMBER DCR A CZ CRECH DO A CR IF IT'S #1 XRA A STA CERC CRLF COUNT TO ZERO * CI55 LDA CIFILE CALL RB JMP CI57 CALL ECHOUT PRINT CHAR LHLD CECT INX H SHLD CECT INCREMENT CHARACTER COUNT * CPI CR JZ CI58 CR -- DONE CPI ';' JZ CI57 ; -- DONE * LXI H,CERC INR M BUMP LINE POSITION MVI A,72 DO AUTO CRLF FOR TTY'S ETC CMP M JNC CI55 NOT PAST, KEEP GOING CALL CRECH PAST 70, TYPE CR JMP CI53 LOOP * ********************* * * * DONE WITH ECHO, MOVE BACK * CI57 CALL CRECHO TYPE A CR * CI58 LHLD CECT MOV B,H MOV C,L BC HAVE NUMBER OF CHARACTERS TYPED LDA CIFILE MVI D,128 CALL SYS DB SPAOP SPACE BACK JMP CIABT ERROR- CAN'T BACK UP * * * * INITIALIZE FOR COMMAND READ * CNBF EQU DKBUF PUT NAME OUT OF THE WAY! * CI59 LXI H,CNBF SHLD CPNT SET STORAGE POINTER MVI A,NMLEN+2 STA CICNT SET MAX CHAR COUNT MVI A,1 STA XQFLG SET XEQ FLAG * * YES, HERE WE AGAIN EAT BLANKS AND COMMAS * CALL CIBNK JZ USRES END OF FILE JMP CI65 GO PROCESS THE FIRST CHR * * * READ COMMAND * CI60 LDA CIFILE CALL RB JMP USRES SHORT RESET TO CONSOLE * CI65 CPI CR JZ CI68 ITS A CR, GO PROCESS CPI SEMI JZ CI68 ITS A SEMICOLON, GO PROCESS CPI BLNK JZ CI71 SPACE, GO PROCESS CPI COMMA JZ CI67 MOV B,A LDA CICNT ORA A ANY MORE CHARACTERS NEEDED? JZ CI60 NO, JUST IGNORE DCR A STA CICNT YES, COUNT DOWN LHLD CPNT MOV M,B STORE CHARACTER INX H MVI M,0 SHLD CPNT UPDATE POINTER JMP CI60 * * * COMMA, INHIBIT EXECUTION * CI67 XRA A STA XQFLG JMP CI71 GO PROCESS * ********************* * * * EAT COMMA'S AND SPACES FROM CI FILE * CIBNK LDA CIFILE CALL RB NOP XRA A SET UP FOR EOF RETURN RET CPI BLNK JZ CIBNK CPI COMMA RNZ JMP CIBNK LOOP FOR " ","," OR EOF * ********************* * * * BACKUP ONE CHARACTER IN CIFILE * CIBUP LDA CIFILE LXI B,1 MVI D,128 CALL SYS DB SPAOP BACKUP 1 CHAR JMP CIABT SERIOUS ERROR RET * ********************* * * * CLOSE LOAD FILE * CICLO LDA CICNT CALL SYS CLOSE DB CLOOP JMP CIABT ERROR RET * ********************* * * * PROCESS COMMAND * * COME HERE FOR CR AND ; * BACKUP SO ROUTINE CAN SEE THE CHARACTER * CI68 LDA CICNT CHECK FOR NULL COMMAND CPI NMLEN+2 CNZ CIBUP BACKUP IF NON-NULL, IF NULL FOLLOWING TEST WILL * DO. CI71 LDA CICNT CPI NMLEN+2 CHECK FOR NULL COMMAND JZ RETURN YES * * OPEN FILE * LXI D,CNBF NAME POINTER CI71A LXI H,-1 SHLD AERR GET MOST ERRORS INX H =0, SYSTEM BUFFER OPTION CALL SYS OPEN FILE DB OPEOP JMP CIOER TRY TO REPORT THE ERROR * STA CICNT SAVE FILE NUMBER LXI H,0 SHLD AERR SET NORNAL ERROR TRAPPING * * CHECK FILE TYPE * LDA FTYPE ANI IMTYPE JNZ CI94 NOT IMAGE FILE, CANT LOAD * * LOAD THE FILE * CI75 LDA CICNT GET FILE NUMBER LXI B,4 4 BYTES LXI D,CBUF INTO CBUF CALL SYS READ BLOCK DB RBLOP JMP CI80 EOF ENCOUNTERED * * * NORMAL RETURN...GET COUNT AND DEST * LHLD CBUF WE READ IT TO HERE MOV B,H MOV C,L BC HAVE COUNT LHLD CBUF+2 HL GET DESTINATION MOV A,B CHECK FOR ZERO COUNT ORA C JZ CI96 YES, PROBABLY UTILITY LDA CICNT A WILL BE NUMBER XCHG . DE HAVE ADDRESS CALL SYS A STILL HAS NUMBER DB RBLOP JMP CI89 BAD LOAD FILE JMP CI75 OK, DO NEXT BLOCK * ********************* * * * CHECK FOR SELF START * CI80 CPI EER0 CHECK FOR EOF JNZ CI98 NOT EOF, VERY BAD MOV A,C CPI 2 ARE 2 BYTES LEFT JZ CI95 YES, SELF START * * CLOSE FILE * CALL CICLO LDA XQFLG IF XQFLG=0 (=> COMMA), ORA A THEN JUST HANDLE NEXT JZ CI59 WITHOUT ECHO JMP RETURN TRY NEXT COMMAND * ********************* * * CI94 MVI A,ERNIF NOT IMAGE FILE JMP CI90 * * * BAD LOAD FILE, CLOSE FIRST * CI89 MVI A,ERBLF * * COME HERE WITH ERROR # IN A * * CI90 PUSH PSW SAE ERROR NUMBER CALL CICLO CLOSE THE LOAD FILE POP PSW A = ERROR # * CIOER STA ERCD SET ERROR NUMBER FOR UTILITY CALL MVI A,CCLDE =CODE FOR LOADER STA EOPR SET OPERATION MVI A,0 MESSAGE AND NO RETURN LXI H,CNBF -> FILE NAME JMP ERRP9 GIVE MESSAGE * ********************* * * * CATESTROPHIC ERROR * CI98 POP H SHOW ADDRESS CI99 MVI A,ERXXX CATESTROPHIC * ********************* * * * ABORT. USE EXISTING REGISTERS * CIABT PUSH PSW RESTORE ECHO FILE TO CONSOLE MVI A,1 STA ECFILE POP PSW CALL SYS DB ABTOP * ********************* * * * * START UP USER PROGRAM * * CLOSE THE FILE * CI95 CALL CICLO LHLD CBUF SET START ADDRESS * * COME HERE WITH HL EQUAL TO START ADDRESS * THE FILE WILL NOT BE CLOSED * CI96 LDA XQFLG ORA A JZ CI59 COMMAND ENDED WITH "," - LOAD NEXT FILE LDA XA PUSH H LHLD XHL RET * PAGE * * ******************************************* * * * * * CONSOLE TELETYPE DRIVER * * SSTA EQU 02 NEW STATUS PORT USTA EQU 0 UDAI EQU 04 NEW INPUT PORT UDAO EQU 1 INRDY EQU 20H READY BIT OTRDY EQU 128 * BUFT EQU 80 BUFFER SIZE IN BYTES (255 MAX) BUFT2 EQU 40 OUTBUF SIZE * ********************* * * DRIVER TABLE * TDRIV DW TDRL READ BLOCK DW TDRL READ NEXT DW IDAC READ LAST, NO CAN DO DW TDWL WRITE BLOCK, NEXT DW TDWL WRITE BLOCK DW TDNGO REWIND DW TDNGO EOF DW TDNGO CLOSE DW IDAC SEEK DW TDCTL CONTROL DW 0 BUFFER SIZE HOLDER DB 1 IMMEDIATE TRANSFER OPTION DW TDNGO INITIALIZE, ETC... A CONVINIENT RETURN * ******************************************* * * * * CONSOLE INPUT DRIVER DISPATCH POINT * CONIN LDA STFLG CHARACTER WAITING? ORA A JZ CONI1 NO XRA A =0 STA STFLG CLEAR FLAG LDA INBYT RETURN WAITING CHR JMP CONI2 GO * ********************* * * * GET CHR FROM RCH DRIVER * CONI1 PUSH H SAVE HL LXI H,CONI2 SETUP RETURN POINT XTHL . RETURN ADDRESS NOW ON STACK PUSH H LHLD RCH GET READ CHARACTER ADDRESS XTHL . GET BACK HL TDNGO RET . DISPATCH TO RCH * ********************* * * * RETURN HERE WITH CHARACTER IN A * CONI2 STA CONCH SAVE IT AWAY PUSH B DON'T DISTURB BC CALL UPSH UPSHIFT CHARACTER LDA CONCH BINARY, RELOAD CHAR POP B NON-BINARY RETURN STA INBYT SAVE BYTE FOR POSSIBLE LATER USE RET * ********************* * * * READ SINGLE BYTE * CIRCH CALL CITCH GET THE STATUS JZ CIRCH WAIT IN UDAI READ IT PUSH PSW SAVE FOR SWITCH TEST LDA SWBIO BINARY I/O? RRC JC CIR20 YES! POP PSW NO ANI 127 MASK PARITY RET * * CIR20 POP PSW RET * ******************************************* * * * CONSOLE STATUS TEST DISPATCH POINT * CONST PUSH H SAVE HL LXI H,CONT20 PUSH H SETUP RETURN ADDRESS LHLD SCH PCHL . DISPATCH TO SCH * * * COME HERE AFTER TEST WITH Z/NZ SET * CONT20 POP H RESTORE HL JNZ CONT30 GOT A CHARACTER WAITING, USE IT LDA STFLG NO REAL CHAR, WHAT ABOUT A PSEUDO ONE ORA A RET . GO WITH FLAGS SET * * * A REAL CHAR, CLEAR PSEUDO CHAR FLAG * CONT30 XRA A STA STFLG INR A DON'T FORGET ABOUT THE REAL ONE RET * * * CONSOLE TEST INPUT CHAR * CITCH IN SSTA NOP . THIS FORMAT CANT BE CHANGED ( OVERLAYED ON RESET ) ANI INRDY RET . FLAGS SET (Z=NO CHAR) * ******************************************* * * * * CONSOLE OUTPUT CHARACTER ROUTINES * CONOUT STA CONCH SAVE CHARACTER CALL UPSH UPSHIFT CHARACTER JMP CON40 RETURN HERE => BINARY SWITCH SET, JUST OUTPUT STA CONCH SAVE UPDATED CHARACTER * * IF CR, SET CRSEEN FLAG AND OUTPUT NULLS * CPI CR JNZ CON20 NOT A CR STA CRSEEN SET FLAG JMP CON90 OUTPUT THE CHARACTER * * * NOT A CR, SEE ABOUT LF * CON20 CPI LF JZ CON30 YES, IT WAS * * NOT A LF, IF LAST WAS CR, OUTPUT LF AND CLEAR CRSEEN * MOV B,A LDA CRSEEN ORA A MOV A,B JZ CON40 LAST WASN'T A CR, JUST OUTPUT CHAR MVI A,LF OUTPUT A LF TO PREVENT OVERPRINTING CALL CON90 * CON30 XRA A STA CRSEEN CLEAR CRSEEN FLAG * * OUTPUT CHAR IN CONCH * CON40 LDA CONCH CON90 CPI LF LF? JZ CON91 YES, FOLLOW WITH NULLS CONXO MOV B,A PUSH H SETUP CALL TO WCH ROUTINE LHLD WCH -> ROUTINE XTHL RET . GET US THERE * * * SEND NULLS AFTER LF * CON91 CALL CONXO TYPE TH ELF LDA NULLS A=LF BEFORE SO NO NEED TO SAVE PUSH D SAVE DE MOV D,A ORA A JZ CON93 NONE TO DO * CON92 XRA A CALL CONXO SEND NULL DCR D COUNT DOWN JNZ CON92 MORE * CON93 POP D MVI A,LF RETURN WIT LF FOR CONSISTANCY RET . NOW RETURN FOR REAL * * * * THIS DOES THE ACTUAL OUTPUT. CONTROL USUALLY COMES HERE * THROUGH (WCH) BY CON90. * CIWCH IN 0F8H STBYT EQU $-1 DB 0 PATCH ROOM ANI OTRDY JZ CIWCH MOV A,B GET CHR OUT 0F9H DABYT EQU $-1 RET * ******************************************* * * * UPSHIFT ASCII SUBROUTINE * * COME HERE WITH CHAR IN CONCH * * BINARY, NO CHANGE, CHAR IN CONCH (NOT IN A) * OK, POSSIBLY UPDATED CHARACTER IN A * UPSH LDA SWBIO BINARY CONSOLE? RRC RC . YES, SKIP THE WHOLE THING AND LET CON.. KNOW * LDA SWUPS SEE IF UPSHIFT REQUESTED RRC LDA CONCH A=CHAR CC UPSH1 CHECK IT JMP RX2 NO, SKIP IT * * * SEE ABOUT UPSHIFTING CHAR * UPSH1 CPI 123 ="z"+1 RNC . >"z", NO CHANGE CPI 97 ="a" RC . <"a", NO CHANGE SBI 32 UPSHIFT RET . OK * ******************************************* * * CI PROMPT MESSAGE * CIMSG DB CR DB LF DB ASTRC THE ACTUAL PROMPT DB 0 END OF MESSAGE * * * OUTPUT STRING TO CONSOLE * * LIKE OUST BUT COME WITH HL -> STRING * THE STRING TERMINATES WITH A ZERO BYTE AND CONTROL * RETURNS TO CALL+1 * OUSTH MOV A,M ORA A RZ INX H CALL CONOUT PRINT JMP OUSTH * PAGE * * ******************************************* * * * ----------------- TTY DRIVER FOR CONSOLE ----------- * TDWB EQU CONOUT OUTPUT CHARACTER ROUTINE * * WRITE BLOCK * * BUFFER ADDR IN HL, COUNT IN DE * TDWL MOV A,E ORA A TEST COUNT JZ TDW30 ZERO, => DONE MOV A,M GET CHAR CALL TDWB PRINT INX H BUMP POINTER DCR E DEC. COUNT JMP TDWL * * * RETURN A ZERO COUNT * TDW30 LXI H,0 JMP RX2 RETURN CALL+2 * * * READ BLOCK * * COME WITH BUFF IN HL, COUNT IN DE * * PRINT PROMPT * TDRL PUSH H PUSH D SAVE IMPORTANT NUMBERS LHLD TDPRO -> PROMPT MESSAGE CALL OUSTH PRINT IT POP D POP H MVI D,0 INITIALIZE CHAR COUNT * TDRL2 CALL CONIN GET A CHARACTER CPI CTRLX CANCEL? JZ TDRLC YES, DELETE LINE CPI BSP BACKSPACE? JZ TDRLB YES, BACKSPACE MOV B,A MOV A,D ONLY CHECK CTRL-C IF D=0 (1ST CHAR) ORA A JNZ TDRL3 SKIP TEST MOV A,B CPI CTRLC CTRL-C ? JZ TDRLE YES, EOF * TDRL3 MOV A,E ORA A JZ TDRLF BUFFER IS FULL MOV M,B STORE CHAR MOV A,B INX H CALL CONOUT ECHO INR D COUNT UP DCR E COUNT DOWN CPI CR IS IT A CR? JZ TDRLQ CR, QUIT JMP TDRL2 GET NEXT. * * * DELETE ENTIRE LINE * TDRLC MVI A,'!' TYPE !,CR, LF CALL TDWB MVI A,CR CALL TDWB MVI A,LF CALL TDWB * * MOV BUFFER POINTER AND COUNTS BACK TO BEGINNING * TDRL5 MOV A,D ORA A JZ TDRL2 INR E MORE CHARS AVAIL DCX H MOVE BACK BUFFER PTR DCR D COUNT DOWN CHARS JMP TDRL5 * * * BACK SPACE * TDRLB MOV A,D ORA A JZ TDRLF ITS EMPTY, FORGET IT DCX H ADJUST POINTER DCR D AND INR E COUNTS. MVI A,LARO CALL TDWB TYPE BACK ARROW JMP TDRL2 AND GO ON * * * END OF FILE ENCOUNTERED. * * **** THIS ROUTINE USED AS INIT ENTRY POINT *** * WATCH OUT!! * TDRLE RET . THATS IT * * BUFFER IS FULL (OR EMPTY) * TDRLF MVI A,BELL CALL TDWB DING JMP TDRL2 TRY AGAIN * * CARRIAGE RETURN-QUIT. * TDRLQ MOV L,D COUNT IN HL MVI H,0 JMP RX2 * PAGE * * ******************************************* * * * * TTY CONTROL/STATUS OPERATION * * HANDLES STATUS AND PROMPT SET REQUESTS * TDCTL ORA A JNZ TDCT2 NOT STATUS REQUEST * MVI A,PALO+PNAT+PATR+PDEL PROTECT WORD LXI D,SBDUP+SBIAT+SBPRO*256 TYPE WORD RET . THAT'S ALL * * * CHECK IF PROMPT SET OPERATION * TDCT2 CPI 2 JNZ TDCER NO, ERROR SHLD TDPRO YES, SET PROMPT POINTER RET * * TDCER CALL ERRL2 DB ERNCT CAN'T DO THAT CONTROL OPERATION * ******************************************* * * * * HERE ARE SOME USEFUL ASCII CHARACTERS * BSP EQU 127 RUBOUT CTRLC EQU 3 CONTROL-C CTRLX EQU 24 CONTROL-X BELL EQU 7 BELL BSLSH EQU 92 BACK-SLASH LARO EQU 95 LEFT ARROW BLNK EQU 32 SPACE * PAGE * * ******************************************* * * * * * UTILITY OPERATION MANAGER * ***************************** * * * THIS OPERATION RUNS ON THE CALLING STACK * * CALL UTIL * OPERATION * ERROR RETURN * NORMAL RETURN * * THE CALLED OPERATION IS PASSED HL AND A * UTILTY SHLD XHL SAVE HL STA XA AND A * * PICKUP THE OPERATION * POP H MOV A,M INX H MOVE RETURN PAST OPER PUSH H STA XOPER SAVE OPERATION * * REWIND THE FILE * LDA UTIL MVI D,0 CALL SYS REWIND DB SPAOP JMP UER2 * * LOAD UTILITY FILE PREFIX * LXI B,255 BC IS COUNT LXI H,CBUF READ INTO CMD BUFFER XRA A A IS ZERO MOV M,A MAKE SURE A ZERO IS THERE XCHG . DE IS DEST ADDRESS * LDA UTIL UTILITY FILE IS ALWAYS OPEN CALL SYS DB RBLOP MEMORY PROTECT WILL SAY NO NOP NOP . IGNORE NOP . EOF * * CHECK OPERATION * LDA XOPER LXI H,CBUF CMP M COMPARE TO MAX JNC UER1 ERROR, ITS TOO BIG * * FIND OPERATION * INX H MOVE PAST MAX MOV C,A MVI B,0 DAD B + OPERATION DAD B MOV A,M INX H MOV H,M MOV L,A = BRANCH ADDRESS ORA H JZ UER1 IT'S ZERO, FORGET IT * * SETUP FOR CI IMAGE LOAD * LDA UTIL STA CICNT NOTE: B= 0 FROM ABOVE CALL SYS DB SEKOP JMP UER2 * * FINAL SETUP FOR CI LOAD IS DONE * MVI A,1 STA XQFLG FORCE EXECUTION....BANG, BANG...SHOOT, STAB JMP CI75 * * * UER1 MVI A,UTE0 BAD UTILITY OPERATION UER2 RET . JUST RETURN WITH SYS STUFF * * * PAGE * * * * * << PTDOS PARAMETER SCANNER >> * * * * VERSION 1.4 MAY 10, 1977 S. DOMPIER * * ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~ * * COMMON VALUES: ( from PTDEF:LB ) * * VALUE +40H = MY BUFFER FROM REG HL * * PSN EQU 5 READ NAME TO REG DE * PSV EQU 85H CONVERT VALUE INTO REG DE * PSFC EQU 6 FORCE CREATE FILE * PSFCO EQU 2 FORCE CREATE AND OPEN FILE * PSC EQU 4 CREATE FILE IF NONE EXIST * PSCO EQU 0 CREATE IF NONE EXIST AND OPEN * PSOP EQU 1 OPEN FILE * PSONE EQU 0A5H READ SINGLE BYTE * PSOPT EQU 8 READ ALL CHRS TO , ; cr 0 * * NOTE: ABOVE VALUES + 40H = USER INPUT BUFFER IN REG HL * * * PSCN EQU 95H CONVERT MY VALUE TO DE, BASE IN REG B * * * PSCAN STA OPT save options SHLD UIBUF save user input buffer address XCHG . (if any) SHLD UOBUF save output (work) buffer address LXI H,0 DAD SP SHLD RSTK save return address LHLD AERR AERR save error switch value SHLD ERSWC LXI H,-1 return to me, my nus one! SHLD AERR AERR set new error switch CALL ERRET set-up normal return address * * normal return * PNRET LDA CC get chr count MOV C,A clear carry, PNR1 ORA A set/reset zero (for chr count). * PNR2 LDA LC get last chacter scanned to reg A LHLD ERSWC reset DOS error switch SHLD AERR LHLD RSTK get return address SPHL . reset caller's stack pointer RET . go home * * * THE REST OF THIS ROUTINE IS USED BY NAMTST IN THE * SYSTEM PROPER...USE CARE!!! * DLMTST CPI '*' RZ . CPI '!' RZ . DLTST CPI '<' special chrs, RETURN IMMEDIATLY RZ . NO CHR COUNT FOR THESE! CPI '>' CHR IS RETURNED IN REG A. RZ CPI '=' RZ * THESE CHRS ARE ILEGAL FOR NMTST...ALREADY TESTED ZERO DLTEST CPI ';' check for normal terminators RZ CPI 0DH RZ CPI ',' RZ ORA A BINARY ZERO RET * PAGE * *************************** * * * * SIMPLE VDM DRIVER * * * * * CHARACTER OUTPUT ROUTINE, CHARACTER PASSED IN B * NULLS, RUBOUT1 * CIVDM MOV A,B GET CHARACTER ORA A NULL? RZ CPI 127 OR RUBOUT? RZ PUSH H NONE OF THOSE, SAVE REGS PUSH D PUSH B SAVE CALLING "B" ANI 7FH STRIP HIGH BIT MOV B,A CPI LF LINE FEEDS MUST GO FROM HERE JZ AGDLY OR CONCH WILL BE CHANGED BY CONIN CALL NCHK SEE IF NEW SPEED ON EACH CHR LDA SPEED GET DELAY MOV H,A COUNT IN HL MVI L,1 * AGAIN DCX H MOV A,H HIGH BYTE OF DELAY ORA A CHECK IT JNZ AGAIN * * END OF DELAY LOOP * AGDLY LHLD VDMAD CURRENT CURSOR ADDRESS MOV A,M ANI 7FH MOV M,A MOV A,B CPI CR HOW ABOUT CR (END OF LINE) JZ PCR1 YES, GO PROCESS IT CPI LARO BACK SPACE? JZ VBKSP IF SO YOU SEE CPI LF NOW TRY LINE FEED LDA KNTT CHAR COUNT IN THIS LINE JZ LFPCR GO TO LINEFEED WITH KNTT INR A + 1 STA KNTT STORE IT BACK CPI 65 CHECK FOR END OF LINE CNC PCR NOT END OF LINE YET MOV M,B OVERWRITE IT WITH CHARACTER INX H POINT TO NEXT LOCATION * GOBK MVI M,' '+80H PUT CURSOR ON SCREEN GOBK1 SHLD VDMAD STORE IT POP B RESTORE REGS POP D POP H MOV A,B RETURN CALLING OUTPUT CHARACTER RET * * * BACKSPACE AND ERASE LAST CHR * VBKSP DCX H LDA KNTT GET CHARACTER COUNT DCR A STA KNTT JMP GOBK * * * CHECK FOR SPEED CONTROL * NCHK CALL CONST RZ . IF NO CHR NCHKA CALL CONIN FOR NEW SPEED CALL CK CHECK FOR NEW SPEED JNC PCR4 IF WASN'T SPEED * NCHK1 ANI 0FH ASCII BIAS MOV C,A SAVE DELAY NUMBER XRA A STC . INIT DELAY BIT IN CARRY * TRY DCR C DEC DELAY NUMBER STA SPEED RZ . STOP NOW RAL . SHIFT DELAY JMP TRY DO IT AGAIN * * * CHECK NEW CHARACTER FOR A NUMBER * CK ANI 7FH JUST IN CASE CPI '9'+1 UPPER LIMIT RNC . NOT NUMBER CPI '1' LOWER LIMIT CMC RET * PCR4 INR A IN CASE OF NULL STA STFLG SAY CHR IS WAITING DCR A RET * * * PROCESS THE CARRIAGE RETURN * PCR1 CALL NCHK SEE IF CHR WAS INPUT JZ PCR3 IF NOT OR IF NEW SPEED * WAIT CPI ' ' CHECK FOR A BLANK JNZ PCR3 NO - CONTINUE WAIT1 XRA A STA STFLG CLEAR FLAG...WE ARE USING THE SPACE * CALL NCHKA JZ PCR3 A NUMBER, CONTINUE CPI ' ' SPACE WILL CONTINUE ALSO JNZ WAIT1 IF IT WASN'T XRA A STA STFLG CLEAR THE FLAG AGAIN * * MOVE CURSOR TO LEFT MOST POSITION (CARRIAGE RET) * PCR3 CALL VDAD1 GET CORNER POSITION MOV A,M GET CHR ORI 80H MOV M,A JMP GOBK1 * * * END OF LINE PROCESSING * LFPCR CALL PCR JMP GOBK * * * LINE FEED OR END OF LINE SCROLL COME HERE * PCR LDA BOT SCROLL CONTROL INR A NEXT ONE PCRCK ANI 0FH KEEP ONLY LOW ORDER 4 BITS STA BOT SAVE IT OUT VPORT OUTPUT TO VDM DB 0,0 <<-------------------<<<<< CALL VDAD1 GET ADDRESS PUSH H SAVE ADDRESS MVI C,64 CHARACTER COUNT * MOVE MVI M,' ' BLANK CHAR ON BOTTOM LINE INX H BUMP POINTER DCR C DECREMENT COUNT JNZ MOVE DO AGAIN POP H GET ADDRESS BACK AGAIN RET * * * CALCULATE SCREEN ADDRESS * VDAD1 XRA A ZERO THE CHR POSITION STA KNTT LDA BOT * VDADD ADI 15 LINE 15 RRC RRC MOV L,A ANI 3 ADI 0FCH MOV H,A MOV A,L ANI 0C0H MOV L,A GOT NEW ADDRESS RET . * * * A FEW VDM EQUATES * VSCREN EQU 0FC00H VDM SCREEN ADDR VPORT EQU 0C8H STANDARD OUTPUT PORT VEND EQU 00 HIGH BYTE OF SCREEN END * ************ PAGE * ** * VERSION: 78.10.04 * * EQUATES * * * ERROR CODES * SIZER EQU ERBSC SIZE CONFLICT FIDER EQU ERFIC FILE ID CONFLICT SECER EQU ERSCC SECTOR CONFLICT FORER EQU ERCFS FORMAT ERROR (CAN'T FIND SECTOR) TRIER EQU ERCRC ABORTS AND CRCC'S TRKER EQU ERCFT CAN'T FIND TRACK RWERR EQU ERRBC READ AFTER WRITE ERROR LOCER EQU ERLOK SYSTEM LOCKED * * * ************************* * * * * *** DISK DRIVER *** * * * * ************************* * * Original source code for ptdos stores the lenght for a * transfer in DRLEN not in the BXD. This MUST be fixed * * * VERSION: 05.01.88 * * Introduction. The disk operating system used on the HELIOS * uses a controller which had the capacity to write and rewrite * both the header and data segments of the disk. This was * achieved by using a hard sectored disk. In addition sector * lengths were variable, up to 4095 bytes long. The IBM format * uses only fixed length sectors, which can never be changed * after definition. Only the fixed length data sectors can be * changed; the headers are fixed and inaccessable once they have * been written. The original data structure used by PTDOS * was a doubly linked list; with linking pointers and filing * information stored in the header for each data block. The * headers changed continually. As this is not available with * soft sectored disks and alternate place must be found to * store the headers. This is the the last 12 bytes of each * sector. When a file block is written to disk the header is * concatenated to the data, before being written. When a block * is read the header is located and transferred from the end of * the block (=sector) to an area reserved for the incoming * header. The RDDSK and WRDSK routines are responsible for * handling the header/data seperation. * * Each file buffer in memory must have the 12 following * bytes spare at the "top end" to put the header. Disk writes * transfer the header from the location OHEAD to this space * befor the block is written. Disk reads move the header to * IHEAD from the end of the block. Merging and seperating * the header and data segments is the responsibility of * RDDSK and WRDSK. * * PTDOS is well protected against its own software being faulty. * It checks the incoming header file id number against the same * data in memory. If these disagree an error is apparent, * and it traps to an error handler. This ensures that if the * linking pointers are incorrect, potentially corrupting the * the disk structure, this will be prevented. * * * TRANSFER COMMANDS * INIOP EQU 00 reset the disk and home to trk 00 RDOP EQU 01 read a block from the disk WROP EQU 02 write * * ERROR CODES * NOER EQU 00 no error detected PAERR EQU 01 parameter error RNFER EQU 02 record not found - can't find sector RDERR EQU 04 read data incorrectly WRERR EQU 08 write error WPERR EQU 16 attempted write to a protected disk UOERR EQU 32 unsupported operation NSERR EQU 64 non standard error - for special devices * user defined error code in A DNRER EQU 128 drive not ready error * * MISC * HELEN EQU 12 LENGTH OF HEADER * PAGE ************************ * * * * * ENTRY POINTS FOR READ AND WRITE DATA * * * * ON CALL: BXD IS TRANSFER DESCRIPTOR AND MUST BE CORRECT * IHEAD OR OHEAD MUST BE CORRECT * RETURNS: CALL+1 FOR NORMAL * ERRL0 FOR ERRORS * * * WRITE DISK BLOCK * WDSK CALL LKCHK CHECK WRITE LOCK AND SET OPERATION JMP WDSK1 * * * READ DISK BLOCK * RDSK MVI A,RDOP READ OPERATION CALL OPSE1 SET OPERATION AND CLEAR INT STUFF * WDSK1 EQU $ * READ HEADER LHLD TSEC GET BLK # FROM PT TRANSFER DESCRIPTOR SHLD HBXFR INTO BXD BLOCK # LXI H,HBXD+1 MVI M,RDOP SET READ CODE DCX H LDA TUNIT INTO DRIVE BXD MOV M,A CALL XFER READ THE HEADER JMP TRYER * CHECK HEADER JUST READ AGAINST TDAD LXI H,TDAD DO THE HEADERS MATCH? LDA IHBLK CMP M JNZ SZCON NO .. ! INX H LDA IHBLK+1 CMP M JNZ SZCON NO .. ! INX H LDA IHSIZ ARE THE FILE BLOCK SIZES THE SAME? CMP M JNZ BLKER INX H LDA IHSIZ+1 CMP M JNZ BLKER INX H LDA IHFID DO THE FILE ID'S MATCH? CMP M JNZ FIERR INX H LDA IHFID+1 CMP M JNZ FIERR LDA OHPRO ARE THERE THE SAME # OF BLOCKS ANI 15 MOV B,A LDA IHPRO ANI 15 CMP B JNZ SZCON * THE HEADERS SEEM TO MATCH .. START TRANSFER LHLD TBCNT GET THE # OF BYTES IN PT BLOCK LXI D,SECTSZ CALL COMP IS TBCNT > SECTOR SIZE? MOV B,H (cy set is HL > DE) MOV C,L cy reset if HL <= sector size JNC WDSK3 NO .. WDSK2 LXI B,SECTSZ YES .. BC has tbcnt or sectz, whichever smlr WDSK3 LXI D,RWBUF LHLD TBUF LDA BXOP CPI RDOP PUSH PSW JZ WDSK4 XCHG . SWITCH SOURCE,DEST. FOR WRITE WDSK4 CALL MOVEV MOVE BC BYTES FROM DE TO HL POP PSW JZ WDSK5 * WRITE BUFFER TO DISK LXI H,HBXD+1 MVI M,WROP DCX H POINT TO START OF BXD TABLE CALL XFER TRANSFER ONE BLOCK .. JMP TRYER * CHECK IF MORE THAN 1 SECTOR TO DO WDSK5 LDA IHPRO ANI 15 DCR A RZ . NO MORE TO DO LHLD TBUF LXI D,SECTSZ DAD D SHLD BXXA LDA TUNIT STA BXDEV LHLD TBCNT LXI D,-SECTSZ DAD D SHLD BXRZ LHLD TDAD INX H SHLD BXFR * DO REMAINING SECTORS WDSK6 LXI H,BXD CALL XFER JMP TRYER * *LDA BXRZ+1 *DCR A TAKE 512 OF # BYTES REMAINING *DCR A *RM . FINISHED *STA BXRZ+1 * * THIS IS THE PATCH TO FIX THE RAM DISK EOS BUG LHLD BXRZ GET RECORD SIZE LXI D,-512 DAD D TAKE OFF 512 FOR THE BLOCK JUST WRITTEN MOV A,H ORA A <0? RM . YES .. WE'RE DONE ORA L ZERO? RZ . YES .. SHLD BXRZ * END OF PATCH LHLD BXFR INX H SHLD BXFR LXI H,BXXA+1 INR M ADD 512 TO DEST. ADDR. INR M JMP WDSK6 * * INITIAL TRANSFER DISCRIPTOR HBXD DB 0,RDOP UNIT,OP DW 512 # BYTES HBXFR DW 0 SECTOR # DW IHEAD BUFFER AT IHEAD AND 500 BYTES AFTER DB 0 RESULT * * * ****************** * * * HERE WE RETURN TO THE SYSTEM * INTD0 DI . NO INTERRUPT XRA A STA IFLG2 SAY WE ARN'T DONE BECAUSE WE WERE LXI H,0 CLEAN HOUSE SHLD INRET BE VERY SURE SHLD INTRT EVERY ONE IS CLEAR SHLD DRVRT EVEN HIM LHLD DSKRT GET BACK SYSTEM STACK SPHL . NORMAL AGAIN *OUT ADRLO RESET CONTROLLER FLAGS * * TEST IF INTERRUPTS SHOULD BE RE-ENABLED AND DO SO IF * TSTEI LDA IFLG1 ORA A RZ . NOPE *EI . YUP RET * * ***************************************** * * * * THIS ENTRY POINT IS FROM DDONE IF A TASK HANDLER * WAS PRESENT. THE HANDLER CALLS HERE WHEN IFLG2 IS * <0>. * INTDN LHLD INTRT SEE IF A TASKER STACK IS LAYING AROUND MOV A,H ORA L JNZ INTD0 SEEMS LEGAL?? * * BAD, BAD, BAD * CALL ERRL0 DB ERIDA ILLEGAL DRIVER ACCESS * * ****************** * * * * INTERRUPT PROCESSING ROUTINES * * * THE EXTERNAL TASK ROUTINE COMES HERE THROUGH THE ENTRY * POINT AREA TO SEE IF WE CAUSED AN INTERRUPT. IF WE * DID THEN CONTROL RETURNS TO THE INTST CALL. IF NOT * THEN CONTROL RETURNS TO THE INTERRUPT HANDLER. * INTDK DI . JUST IN CASE LHLD INRET WAS IT US? MOV A,H ORA L RZ . COULDN'T BE US...WE'RE NOT HERE!!! PCHL . GO FIND OUT IF WE DID * ******************* * * * WRITE DISK HEADER (AND DATA) WDSKH *** * * * OHEAD IS SET UP BY CALLER * * WRITE HEADER FOLLOWED BY DATA BLOCK * WDSKH EQU $ LHLD OHFID SHLD TFID CALL LKCHK LHLD TSEC SHLD OHEAD SHLD HBXFR MOV A,L ANI 7 MOV B,A LDA TUNIT STA HBXD SET UNIT * * CHECK FOR WRITE OVER INDEX * LDA OHPRO ANI 7 ADD B CPI 9 JNC SZCON ERROR- BLOCK CROSSES TRACK DIVISION LXI H,IHEAD LXI D,OHEAD CALL MOVEF DB HELEN JMP WDSK2 TRANSFER DATA NOW * ************** * * TEST IF SYSTEM IS LOCKED * * ERROR THROUGH ERRL0 * NORMAL SET OPERATION AND RETURN * LKCHK LDA SWLOK TEST IF WRITE LOCKED RRC JC LOKER YES, SWITCH IS SET MVI A,WROP * * SAVE OPERATION AND CLEAR THE TASK AND INTERRUPT * STUFF * OPSE1 STA BXOP SET OPERATION FOR LATER LXI H,0 SET UP STACK FOR RETURN POP D GET THIS CALL OFF STACK DAD SP GET SYSTEM RETURN WITH STACK SHLD DSKRT PUSH D OUR CALL GOES BACK ON JMP BLKLN SET UP TRANSFER PARAMETERS AND RETURN * * * * * * THIS ROUTINE CALCULATES THE TRANSFER SIZE FROM THE * HEADER INFORMATION AND SETS THE NUMBER OF SECTORS * INTO OHPRO. * * BLKLN LHLD TBCNT GET COUNT FROM TRANSFER DESCRIPTOR SHLD OHSIZ CALL AFCALC CALCULATE NUMBER OF SECTORS LDA OHPRO OUTGOING HEADER PROTECTION WORD ANI 80H CLEAR PREVIOUS COUNT ORA C ADD IN THE SECTOR COUNT STA OHPRO PUT IT BACK RET * * * ****************** * * * DISK ERROR PROCESSOR * FMTER CALL DEREP CAN'T FIND SECTOR DB ERCFS * BLKER CALL DEREP SIZE CONFLICT DB ERBSC * FIERR CALL DEREP FID CONFLICT DB ERFIC * SZCON CALL DEREP SECTOR CONFLICT DB ERSCC * TRYER CALL DEREP DRIVER ERROR DB ERDRI * ERTRK CALL DEREP DB ERCFT * LOKER CALL DEREP SYSTEM LOCKED DB ERLOK * ****************** * * * DISK ERROR REPORT ROUTINE * * CONTROL GOES TO ERRL0 EVENTUALLY * CALL WITH CALL+1 = ERROR # * DEREP CALL DREP PRINT ID, TRACK, ETC. JMP ERRL0 JUST GIVE ERROR * * * SUBROUTINE TO PRINT FILE ID, TRACK, IHFID, IHSIZ * AS A PREFIX TO AN ABORT MESSAGE * BUT,... SKIP IF ERROR IS USER TRAPPED * DREP LHLD FERR MOV A,H ORA L IS SOMEONE ELSE HANDLING THE ERROR? RNZ . YES, NOTHING TO DO CALL OUST SAY SOMETHING DB CR DB LF ASC "DSK:" DB 0 * CALL O16N PRINT # POINTED TO BY CALL+1, ALSO BLANK DW TFID CALL O16N DW TDAD TRACK AND SECTOR CALL O16N DW IHFID CALL O16N DW IHSIZ RET * ****************** * * * ERROR HANDLER FOR SYSTEM * * *** NOTE *** * * EOPR AND ERCD GET MODIFIED BY THE SYSTEM * ERRP9 CALL UTILTY DO THE ERROR TYPEOUT DB UXOP JMP SRE50 ERROR!!! EOPR DB -1 DOS OPERATION ERCD DB -1 ERROR CODE JMP SRE50 JUST IN CASE OF SCREWUPS * * * PAGE *********************** * * * * DEFINE THE TOP OF THE SYSTEM * * MEMTOP EQU 0C000H ABSOLUTE TOP * ORG MEMTOP DEFINE THE BIG BUFFERS * DS -256 COME DOWN ONE SECTOR SIZE DS -320 PLUS ANOTHER BIG ONE OLBUF EQU $ OVERLAY BUFFER * DS -256 NOW ANOTHER SECTOR CXBUF EQU $ COMMAND EXECUTION BUFFER * * * * NOW FOR THE TOP OF THE SYSTEM * SYSTOP EQU $-1 * NUENT EQU 15 NUMBER OF JUMP ENTRYS EPLEN EQU 3*NUENT+6 JUMPS+DW * ORG SYSTOP-EPLEN LENGTH OF ENTRY POINT AREA * * * FIXED ENTRY POINT AREA * DW CIVDM -> VDM DRIVER OUTPUT CHAR DW CIWCH -> TERMINAL OUTPUT CHAR JMP SDIRY SEARCH DIRECTORY BY ID JMP INTDK CONTINUE INTERRUPT PROCESSING JMP INTDN PROCESSING DONE JMP PSCAN PARAMETER SCANNER JMP CONST CONSOLE TEST INPUT JMP CONOUT CONSOLE OUTPUT 1 CHAR JMP CONIN CONSOL INPUT 1 CHAR DW CIFILE FIXED PARM AREA JMP ERRL2 ERROR LEVEL I JMP ERRL1 1 JMP ERRL0 0 JMP USRES SHORT RESET JMP UTILTY UTILITY CALL JMP WB WRITE BYTE JMP RB READ BYTE JMP SYS MAIN CALL * AP2 EQU $ LAST BYTE + 1 OF RESIDENT * PAGE * * * * * * * ONCE ONLY CODE FOLLOWING BOOTSTRAP. * * THIS CODE LOADS THE SYSTEM GLOBAL AREA AND * ADJUSTS THE INITIAL FCBS'S POSITIONS. * ORG CXBUF PART OF THE SYSTEM * RESET DI . LXI SP,CISTK SETUP STACK LXI H,SAM+7FFH MAKE SURE THAT THIS VERSION OF PTDOS MATCHES LDA REVNR THE DRIVER IN SAM CMP M DOES IT? JNZ REVER NO .. !! THEN ABHORT THE BOOTING LXI H,0 SHLD DSKRD CLEAR THE DRIVE NOT READY TRAP SHLD AERR CLEAR ANY ERROR HANDLING SHLD FERR SHLD EERR DCX H =-1 SHLD BDSK1 CLEAR ANY INTERRUPT LINK SHLD BDSK2 XRA A STA IFLG1 DON'T RESTORE INTERRUPTS MVI A,2 SET MAXUN TO 2 TO INITIALIZE PROPERLY STA MAXUN CALL DDRI INITIALIZE DISK DRIVER * * LOAD THE SYSTEM GLOBAL AREA * LXI D,RESPA LXI H,TDAD CALL MOVEF MOVE SYSGLOBL DESCRIPTOR DB TUNIT-TDAD+1 * CALL RDSK READ IT IN * * NEXT, MOVE THE FCB'S TO THE RIGHT PLACE * LXI D,SP1 MOVE FROM HERE LHLD FCBASE TO HERE LXI B,MINFCB*LNFCB = LENGTH CALL MOVEV * * ZERO THE UNUSED FCB'S * LHLD FCBASE LXI D,LNFCB = FCB LENGTH LDA SYSFIL = NUMBER OF ALLOCATED FCB'S * INI10 ORA A JZ INI20 HL -> FIRST UNUSED FCB, GO ZERO DAD D DCR A JMP INI10 * * INI20 XCHG . DE -> FIRST WORD TO ZERO LXI H,SGAREA HL -> FIRST WORD NOT TO ZERO INI25 CALL COMP JNC INI30 ALL DONE XRA A = 0 STAX D INX D JMP INI25 OK FOR NEXT * * * INITALIZE I/O DRIVERS * * IF SOLOS/CUTER, SEND I/O TO SAME PLACE AS CURRENT * PSEUDO-PORT. ELSE, SEND IT TO CUTER-TYPE SERIAL PORT. SAM EQU 0F000H * INI30 LXI H,VSCREN INITIALIZE VDM SHLD VDMAD SO USER CAN DO AN OUT V COMMAND LATER XRA A STA BOT STA KNTT STA SPEED * LDA SAM THERE IS, DETERMINE WHICH LXI D,SOLTAB ASSUME SOLOS TILL PROVEN GUILTY CPI 0 JZ INI40 SOLOS EXISTS LXI D,CUTTAB ASSUME CUTER SINCE IT WASN'T SOLOS * INI40 LHLD SAM+1AH GET OUTPUT PSEUDO-PORT NUMBER MOV A,M CALL LKTAB MOVE TO PROPER TABLE ENTRY CALL MODO NOW UPDATE THE INTERNAL OUTPUT DRIVERS * LHLD SAM+20H GET INPUT PSEUDO-PORT NUMBER MOV A,M CALL LKTA2 MOVE TO THE PROPER TABLE ENTRY CALL MODI NOW UPDATE THE INTERNAL INPUT/TSTCHR DRIVERS * LHLD SAM+1AH GET OUTPUT PSEUDO-PORT NUMBER MOV A,M ANI 3 IS IT VDM? JNZ INI60 NOPE LHLD WCH YES-SET DRIVER POINTER TO VDM DRIVER LXI D,-CIWCH DAD D MOV A,H ORA L JNZ INI60 UNLESS, OF COURSE, USER HAS ALLREADY CHANGED IT LXI H,CIVDM SHLD WCH XRA A OUT VPORT CALL OUST CLEAR SCREEN DB CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF DB CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF DB 0 JMP INI60 * * * SAY IT ALL * INI60 CALL OUST SAY SOMETHING DB CR,LF,CR,LF,CR,LF ASC "PTDOS 2.0 Rev AA Nov 88" DB CR,LF ASC "Copyright 1978" DB CR,LF ASC "Processor Technology Corporation" DB CR,LF ASC "Implemented Feb 88 by D. Sherratt" DB CR,LF DB 0 * * SEE IF WE WANT A LOG FILE * LDA SWLOG GET LOG FILE SWITCH ORA A JZ INVRB * INLOG LXI H,-1 STATIC BUFFERING SHLD AERR SHLD EERR SHLD FERR INX H LXI D,LNAME THE LOG FILE NAME CALL SYS DB OPEOP OPEN IT * JMP INCRE SHLD AERR SHLD FERR MVI D,-1 CALL SYS DB SPAOP SPACE TO END JMP USRES RESET IF NOT STA ECFILE SET AS ECHO FILE INR A STA SYSFIL CAN'T CLOSE IT NOW XRA A STA UA SET FOR NO ERROR REPORT FROM RESET JMP INVRB * * INCRE CPI ERNEX DOESN'T EXIST? JNZ USRES LXI D,LCBLK CALL SYS DB CREOP CREATE IT JMP USRES JMP INLOG * * * OPEN AN INPUT FILE FOR GOOD COMMANDS * INVRB LDA SWVRB SEE HOW TALKATIVE WE ARE ORA A JZ SRESET OPEN ONLY IF VERBOSE IS WANTED LXI D,CNAME NAME OF FILE LXI H,0 STATIC BUFFERING CALL SYS DB OPEOP JMP USRES SHORT RESET IF ERROR STA CIFILE IT IS FOR INPUT CALL SYS DB RETOP RETURN TO RUNIT * REVNR EQU $ DB 0AAH THIS BYTE MUST MATCH THE LAST BYTE IN SAM ROM * OR THE DRIVER WILL CORRUPT PTDOS FILES REVER EQU $ CALL OUST DB LF,CR ASC "THIS VERSION OF PTDOS DOES NOT MATCH THE DISK DRIVER" DB LF,CR ASC "IN SAM. BOOT ABHORTED !" DB LF,CR,0 JMP SAM+4 QUIT * * * CNAME ASC "start.up/0" THE SYSTEM START UP FILE LCBLK DB 80H TYPE DW 256 BLOCK SIZE DB 0 NO ATTRIBUTES LNAME ASC "syst.log/0" THE SYSTEM LOG FILE * * * * SYSTEM GLOBAL FILE DESCRIPTOR * RESPA DW DASPB SECTOR # DW LNSPA LENGTH DW IDSPA FILES ID NO. DW MASPA LOAD ADDRESS DB 0 UNIT * * * * * * * * * DRIVE AND DRIVER INITIALIZATION ROUTINES * * THIS ROUTINE INITIALIZES ALL DRIVES AND SETS THE * TRACK COUNT VALUES IN THE UNIT TABLE TO ZERO. * DDRI LDA MAXUN NO. OF DRIVES TO RESTORE DDRI1 DCR A LXI H,BXD+1 MVI M,INIOP OPCODE FOR INITIALISE DCX H =BXD =UNIT MOV M,A =HIGHEST UNIT NO. DDRI2 CALL XFER NOP NO ERRORS FOR INITIALISE NOP NOP LXI H,BXD DCR M NEXT UNIT RM FINISHED JMP DDRI2 * * * * * **************************************************************** * * MOVE TO TABLE ENTRY SPECIFIED BY A (TABLE POINTED TO BY DE) * LKTA2 INX D ENTRY HERE FOR INPUT TABLE INX D (INPUT IS 4 BYTES PAST OUTPUT) INX D INX D LKTAB MOV H,D ENTRY HERE FOR OUTPUT TABLE MOV L,E ANI 3 CPI 3 JNZ LKTA5 MVI A,1 IF PSEUDO-PORT WAS 3 (CUSTOM), MAKE IT A 1 (SERIAL) LKTA5 ADD A ENTRIES ARE 8 LONG, SO MULTIPLY BY 8 ADD A ADD A MOV C,A MVI B,0 DAD B ADD TO CORRECT ENTRY RET . RETURN WITH HL POINTING TO ENTRY DESIRED * ************************* * MODO MOV A,M MODIFY OUTPUT DRIVERS STA STBYT INX H MOV A,M STA STBYT+1 INX H MOV A,M STA STBYT+3 INX H MOV A,M STA DABYT RET . * MODI MOV A,M MODIFY INPUT DRIVERS STA CITCH+1 INX H MOV A,M STA CITCH+2 INX H MOV A,M STA CITCH+4 INX H MOV A,M STA CIRCH+7 RET . * **************************************** * * I/O DRIVER MODIFICATION TABLES * * NOTE: IF THE CURRENT-PSEUDO PORT WAS 0, THE DRIVER * GETS MODIFIED TO THE SERIAL PORT, BUT THE SYSGLOBL * POINTER POINTS TO THE VDM DRIVER INSTEAD. SO IF AN * OUT P COMMAND IS DONE, OUTPUT WILL GO SERIAL. * ******************** * SOLTAB EQU $ TABLE FOR SOLOS-TYPE PORTS * ***** IF CURRENT PSEUDO-PORT WAS ZERO (VDM/KBD) * DB 0F8H OUTPUT STATUS PORT NOP . DON'T INVERT STATUS BITS DB 080H MASK FOR READY BIT DB 0F9H OUTPUT PORT * DB 0FAH INPUT STATUS PORT CMA . DB 1 MASK FOR READY BIT DB 0FCH INPUT PORT * ***** IF CURRENT PSEUDO-PORT WAS 1 OR 3 (SERIAL) * DB 0F8H NOP . DB 80H DB 0F9H * DB 0F8H NOP . DB 40H DB 0F9H * ***** IF CURRENT PSEUDO-PORT WAS 2 (PARALLEL) * DB 0FAH CMA . DB 4 DB 0FDH * DB 0FAH CMA . DB 2 DB 0FDH * ******************** * CUTTAB EQU $ TABLE FOR CUTER-TYPE PORTS * ***** IF CURRENT PSEUDO-PORT WAS 0 (VDM/KBD) * DB 0 NOP . DB 80H DB 1 * DB 2 PARALLEL KBD NOP . DB 20H DB 4 * ***** IF CURRENT PSEUDO-PORT WAS 1 OR 3 (SERIAL) * NEITAB DB 0 THIS TABLE IS ALSO USED IF NEITHER SOLOS OR CUTER NOP . DB 80H DB 1 * DB 0 NOP . DB 40H DB 1 * ***** IF CURRENT PSEUDO-PORT WAS 2 (PARALLEL) * DB 0 CMA . DB 4 DB 2 * DB 0 CMA . DB 2 DB 2 * **************************************************************** * PAGE * * * * ORG 07000H * * * SYSTEM LOADER * * THIS SET OF ROUTINES WHOSE STARTING ADDRESS * IS LISTED ABOVE ESTABLISHES AN INITIAL SYSTEM * ON A PRE-WRITTEN DISK IN DRIVE 0, UNIT 0. * * * START AT LDR01 TO JUST REWRITE THE SYSTEM LEAVING * EVERYTHING ELSE ALONE * * LDR XRA A STA UPFLG LDR01 LXI SP,LDSTK SET STACK UP CALL LDRI INITIALIZE DRIVER * * WRITE OUT RESIDENT * LXI D,LRES CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LRESH CALL LPHD SET OUTGOING HEADER CALL LWDSH WRITE OUT * * LXI D,LRES2 CALL LPTD SET TDAD LXI D,LRESD CALL LPHD SET OHEAD CALL LWDSH WRITE OUT * * WRITE OUT SYSTEM GLOBAL AREA * LXI D,LSGL CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LSGLH CALL LPHD SET OUTGOING HEADER CALL LWDSH WRITE OUT * * IF UPDATE ONLY, STOP * LDA UPFLG ORA A JNZ LDR60 * * WRITE OUT BOOTSTRAP * *LXI D,LBOO *CALL LPTD SET TRANSFER DESCRIPTOR *LXI D,LBOOH *CALL LPHD SET OUTGOING HEADER *CALL LWDSH WRITE OUT * DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 * WRITE NEXT ID FILE * LXI D,LNIF CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LNIFH CALL LPHD SET OUTGOING HEADER CALL LWDSH WRITE OUT * * INITIALIZE EMBRYONIC DIRECTORY * * WRITE FIRST SECTOR * LXI D,LDS0 CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LDS0H CALL LPHD SET OUTGOING HEADER CALL LWDSH WRITE OUT * LOOP AND WRITE REST OF DIRECTORY MVI A,DICNT-2 STA LDCNT SET COUNT OF REMAINING SECTORS * SET HEADERS LXI D,LDS1 CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LDS1H CALL LPHD SET OUTGOING HEADER * * IF LAST SECTOR, SET EOF * LDR20 LDA LDCNT ORA A =O? JNZ LDR30 NO, NOT LAST SECTOR * SET EOF LXI H,EOFCD LXI D,SECTSZ DAD D EOF+COUNT SHLD LOHFOR SET IN FORE PTR. * LDR30 CALL LWDSH WRITE * UPDATE POINTERS LXI H,LTSEC PTR TO SECTOR ADDRESS INR M LXI H,LOHFOR PTR TO SECTOR FORE PTR INR M LXI H,LOHBAK PTR TO SECTOR BACK PTR INR M * CHECK COUNT LDA LDCNT ORA A JZ LDR40 DCR A NOPE STA LDCNT JMP LDR20 DO NEXT SECTOR. * * LDR40 MVI B,80 MVI A,-1 LXI H,FMBF * ZERO THE FSM LDR42 MOV M,A INX H DCR B JNZ LDR42 LXI H,FMBF INR A =0 MOV M,A INX H MOV M,A INX H MOV M,A LXI H,FMBF+25 DIR TRK MOV M,A INX H MOV M,A FSM,NID * WRITE OUT FSM LXI D,LFSM CALL LPTD SET TRANSFER DESCRIPTOR LXI D,LFSMH CALL LPHD SET OUTGOING HEADER CALL LWDSH * * * LOAD COMPLETE * * LDR60 CALL OUST DB LF,CR CRLF ASC 'Load Complete DB LF,CR AGAIN DB 0 DONE JMP 0F004H HEAD ON UP TO SAMDI * * * PREPARE TRANSFER DESCRIPTOR * LPTD LXI H,LTDAD CALL MOVEF DB LTUNIT-LTDAD+1 RET * * PREPARE OUTGOING HEADER * LPHD LXI H,LOHFOR CALL MOVEF DB OHPRO-OHFOR+1 RET * * * THESE TABLES DESCRIBE THE MODULES TO BE * LOADED. * * RESIDENT * * LRES DW DAREB DISK ADDRESS DW 4084 LENGTH DW IDRES ID DW 0A002H ADDRESS <<-----------------<< WATCH MARES!! DB 0 UNIT * LRESH DW D2REB FORE DW BOFCD DW IDRES DB 0 (PROTECTION) * * LRES2 DW D2REB SECTOR DW 4084 LENGTH DW IDRES ID DW 0AFF6H ADDRESS DB 0 UNIT * LRESD DW EOFCD+4084 FORE DW DAREB BACK DW IDRES ID DB 0 PROT * * BOOTLOAD * BOLEN EQU FULSZ+SECTSZ TWO SECTORS WORTH * LBOO DW DABOS SECTOR DW BOLEN LENGTH DW IDBOT ID DW 0F900H ADDRESS DB 0 UNIT * LBOOH DW EOFCD+BOLEN FORE (BOCNT=BOLEN ???) DW BOFCD BACK DW IDBOT ID DB 0 PROTECTION * * SYSTEM GLOBAL * LSGL DW DASPB SECTOR DW LNSPA COUNT DW IDSPA ID DW SP1 MEMORY ADDRESS DB 0 UNIT * LSGLH DW SP2-SP1+1+EOFCD DW BOFCD BACK DW IDSPA ID DB 0 PROT. * * NEXT ID FILE * LNIF DW DANIB SECTOR DW NIDBC COUNT DW IDNID ID DW LIDBF ADDRESS DB 0 UNIT * LNIFH DW EOFCD+NIDBC FORE DW BOFCD BACK DW IDNID ID DB 0 PROT. * * FSM * LFSM DW DAFSB SECTOR DW 80 LENGTH DW IDFSM ID DW FMBF ADDR DB 0 UNIT * LFSMH DW EOFCD+80 FORE DW BOFCD BACK DW IDFSM ID DB 0 PROTECT * * DIRECTOR SECTOR 0 * LDS0 DW DIRDB SECTOR DW SECTSZ SIZE DW IDDIR ID DW DS0 ADDRESS DB 0 UNIT * LDS0H DW DIRDB+1 FORE DW BOFCD BACK POINTER DW IDDIR ID DB 0 PROT. * * DIRECTORY SECTORS 1 TO 15 * LDS1 DW DIRDB+1 SECTOR DW SECTSZ SIZE DW IDDIR ID DW DS1 ADDRESS DB 0 UNIT * LDS1H DW DIRDB+2 FORE DW DIRDB BACK DW IDDIR ID DB 0 UNIT * * * INITIAL DIRECTORY * FIRST SECTOR * * DS0 DB 6 NUMBER OF ENTRIES DW DS0N-DS0 NEXT ENTRY DISPLACEMENT * ASC 'DIRECTRY' DB BNTYP TYPE DW SECTSZ BLOCK SIZE DB PDEL+PWRI+PFINF+PATR+PNAT DW IDDIR ID DW 0 INDEX FILE POINTER DW DIRDB DISK DW DICNT BLOCK COUNT * ASC 'NEXTID' DB 0 DB 0 DB BNTYP TYPE DW NIDBC BLOCK SIZE DB PDEL+PWRI+PATR+PNAT+PFINF DW IDNID ID DW 0 INDEX DW DANIB FBA DW 1 BLOCK COUNT * ASC 'FSMAP' DB 0 DB 0 DB 0 DB BNTYP TYPE DW 80 BLOCK SIZE DB PDEL+PWRI+PATR+PNAT+PFINF DW IDFSM ID DW 0 INDEX DW DAFSB DA DW 1 BLOCK COUNT * ASC 'SUTIL' DB 0 DW 0 DB BNTYP TYPE DW 500 BLOCK SIZE DB PDEL+PNAT+PFINF DW 8 ID DW 214 INDEX DW 210 DISK DW 4 BLOCK COUNT * ASC 'SYSGLOBL' DB BNTYP TYPE DW LNSPA BLOCK SIZE DB PDEL+PWRI+PATR+PNAT+PFINF DW IDSPA ID DW 0 INDEX DW DASPB DISK DW 1 BLOCK COUNT * ASC 'RESIDENT' DB BNTYP TYPE DW 4084 BLOCKSIZE DB PDEL+PWRI+PREA+PFINF+PATR+PNAT DW IDRES ID DW 0 INDEX DW DAREB DA DW 2 BLOCK COUNT DS0L EQU $ * DS0N EQU DS0L DISPLACEMENT TO NEXT ENTRY * * * IMAGE OF REMAINDER OF DIRECTORY SECTORS * * DS1 DB 0 NUMBER OF ENTRIES DW 3 NEXT ENTRY DISPLACEMENT DW 0 * * NEXT ID FILE IMAGE * LIDBF DW 22H NEXT FILE ID. * * * TEMP STORAGE FOR LOADER * * LDCNT RES 1 DIRECTORY ENTRY COUNTER UPFLG DB 1 * * TRANSFER DESCRIPTOR * LTDAD RES 2 DISK ADDRESS LTSEC EQU LTDAD LTBCNT RES 2 BYTE COUNT LTFID RES 2 FILE ID LTBUF RES 2 BUFFER ADDRESS LTUNIT RES 1 UNIT * * INCOMMING HEADER * LIHEAD RES 2 DISK ADDRESS LIHSEC EQU LIHEAD LIHFOR RES 2 FORE LIHBAK RES 2 BACK LIHFID RES 2 ID LIHPRO RES 1 PROT-SIZE LIHSIZ RES 2 BLOCK SIZE LIHSPR RES 2 EXPANSION ROOM * * OUTGOING HEADER * LOHSEC RES 2 SECTOR AND TRACK BUFFER LOHFOR RES 2 FORE LOHBAK RES 2 BACK LOHFID RES 2 ID LOHPRO RES 1 PROT-SIZE LOHSIZ RES 2 BLOCK SIZE LOHSPR RES 2 MORE ROOM * LOHEA EQU LOHSEC * * LOADER STACK * RES 20 LDSTK DB 0 * FMBF DS 80+2 BEGINNING OF 80 ZERO BUFFER * * BUFEND EQU $ * * * DISK WRITE ROUTINES FOR SYSTEM LOADER * LDRI MVI A,1 ONLY INITIALISE 1 DRIVE JMP DDRI1 * * * LWDS2 LXI B,SECTSZ LXI D,RWBUF LHLD LTBUF XCHG . SWITCH SOURCE,DEST. FOR WRITE CALL MOVEV * WRITE BUFFER TO DISK LXI H,HBXD+1 MVI M,WROP DCX H POINT TO START OF BXD TABLE CALL XFER JMP SZCON * CHECK IF MORE THAN 1 SECTOR TO DO LWDS5 LDA IHPRO ANI 15 DCR A RZ . NO MORE TO DO LHLD LTBUF LXI D,SECTSZ DAD D SHLD BXXA LDA LTUNIT STA BXDEV LHLD LTBCNT LXI D,-SECTSZ DAD D SHLD BXRZ LHLD LTDAD INX H SHLD BXFR * DO REMAINING SECTORS LWDS6 LXI H,BXD CALL XFER JMP SZCON LHLD BXRZ LXI D,-FULSZ DAD D SHLD BXRZ MOV A,H ORA A RM . FINISHED ORA L RZ . LHLD BXFR INX H SHLD BXFR LXI H,BXXA+1 INR M ADD 512 TO DEST. ADDR. INR M JMP LWDS6 * * * WRITE DISK HEADER (AND DATA) LWDSH *** * * * LOHEAD IS SET UP BY CALLER * * WRITE HEADER FOLLOWED BY DATA BLOCK * LWDSH EQU $ MVI A,WROP STA BXOP LHLD LOHFID SHLD LTFID CALL LBLKL LHLD LTSEC SHLD LOHEAD SHLD HBXFR XRA A STA HBXD UNIT 0 MOV A,L ANI 7 MOV B,A * * CHECK FOR WRITE OVER INDEX * LDA LOHPRO ANI 7 ADD B CPI 9 JNC SZCON ERROR- BOLCK CROSSES TRACK DIVISION LXI H,IHEAD LXI D,LOHEAD CALL MOVEF DB HELEN JMP LWDS2 TRANSFER DATA NOW * * * THIS ROUTINE CALCULATES THE TRANSFER SIZE FROM THE * HEADER INFORMATION AND SETS THE NUMBER OF SECTORS * INTO LOHPRO. * * LBLKL LHLD LTBCNT GET COUNT FROM TRANSFER DESCRIPTOR SHLD LOHSIZ CALL AFCALC CALCULATE NUMBER OF SECTORS LDA LOHPRO OUTGOING HEADER PROTECTION WORD ANI 80H CLEAR PREVIOUS COUNT ORA C ADD IN THE SECTOR COUNT STA LOHPRO PUT IT BACK RET * * *