;******************************************************* ;**** THIS IS THE NORTH STAR DISK OPERATING **** ;**** SYSTEM AS DIS-ASSEMBLED BY BARRY WATZMAN, **** ;**** CCP, CDP. NO WARRANTIES ARE MADE AS TO **** ;**** THE CORRECTNESS OF THIS DIS-ASSEMBLY, **** ;**** THOUGH THE AUTHOR IS NOT AWARE OF ANY ERROR **** ;**** IN IT. THIS WORK WAS DERIVED FROM VERSION **** ;**** 2 RELEASE 3, WHICH INCLUDES LINE EDITING, **** ;**** AND INCLUDES THE FIX FOR THE 134 BLOCK **** ;**** LOCKUP BUG DISCOVERED BY THE AUTHOR **** ;**** (AT 24CFH). NORTH STAR COMPUTERS INC. IS **** ;**** AWARE OF THIS PUBLICATION AND HAS AUTHORIZED **** ;**** IT'S RELEASE ON A LIMITED WORD OF MOUTH ONLY **** ;**** (NO ADVERTISING) BASIS IN AN AGREEMEMT **** ;**** BETWEEN DR. CHARLES GRANT AND THE AUTHOR IN **** ;**** NOV., 1977. THE NORTH STAR DOS PROGRAM IS **** ;**** COPYRIGHT 1977 BY NORTH STAR COMPUTERS, INC. **** ;**** THIS LISTING IS COPYRIGHT 1977 BY BARRY A. **** ;**** WATZMAN, CDP. ADDITIONAL COPIES MAY BE **** ;**** OBTAINED FOR $25.00 FROM THE AUTHOR AT 2330 **** ;**** MILLENNIUM LN., RESTON, VA. 22091. THE **** ;**** AUTHOR WOULD APPRECIATE BEING NOTIFIED OF **** ;**** CORRECTIONS OR ADDITIONS TO THE UNCOMMENTED **** ;**** PORTIONS OF THE LISTING. **** ;******************************************************* ;PAGE ;******************************************************** ;**** THE NORTH STAR DISK OPERATING SYSTEM AS **** ;**** DIS-ASSEMBLED BY BARRY A. WATZMAN, CDP **** ;******************************************************** ;**** THIS IS THE BOOT-STRAP ROUTINE IN PROM **** ;******************************************************** BOARD EQU 0E800H ;CONTROLLER BOARD ADDR BRD EQU 0E8H ;BOARD PAGE DOS EQU 2000H ;DOS ADDRESS SYNCF EQU 04H ;SYNC CHAR FOUND-RDY TO READ SCTPS EQU 0FH ;SECTOR POSITION MASK TRAK0 EQU 01H ;TRACK ZERO MASK MOTST EQU 10H ;MOTOR ON TEST MASK SETFF EQU BOARD+309H ;SET TRACK STEP FF RESFF EQU BOARD+308H ;RESET TRACK STEP FF ASTMS EQU BOARD+390H ;LOAD A STAT & START MOTR ASTAT EQU BOARD+310H ;LOAD A STAT ONLY BSTAT EQU BOARD+330H ;LOAD B STAT ONLY RSFLG EQU BOARD+314H ;RESET SECTOR FLAG STPIN EQU BOARD+31DH ;LOAD STEP DIR 'IN' STPOU EQU BOARD+31CH ;LOAD STEP DIR 'OUT' RDATA EQU BOARD+350H ;MASK TO READ DATA FROM DISK ;******************************************************** ;**** THIS SECTION PERFORMS NECESSARY INITIALIZATION **** ;**** SO THAT THE NORMAL BLOCK READ ROUTINE AT E91EH **** ;**** MAY BE CALLED. NOTE THAT THE MAX NO OF TRACK **** ;**** MOVEMENTS TO GET THE HEAD TO TRACK 0 IS 58 - **** ;**** THE AUTHOR APPARENTLY ADDED ONE FOR SAFETY BUT **** ;**** FORGOT THAT THE 58 WAS DECIMAL, NOT HEX. **** ;******************************************************** ORG BOARD+100H LXI SP,DOS+114H MVI B,10 ;READ 10 TIMES THEN GIVE UP LE905 PUSH B MVI A,59H ;58D=MAX NO OF MOVES TO TRAK 0 STA DOS ;ASSUME HEAD AT WORST CASE LOC STA DRSEL ;NONE OF THREE DRIVES SELECTED LXI B,0001H ;B BECOMES DESIRED TRK;C=DRIVE MOV A,C ;READ ONLY 1 SECTOR MVI D,4 ;D=BLK TO BE READ WITHIN TRACK MOV E,C ;COMMAND;1 = READ LXI H,DOS ;ADDRESS OF DOS TO BE LOADED CALL LE91E ;MAIN PROCESSING LOOP JMP CKBS ;IF OK EXIT ELSE RETRY OR DIE ;******************************************************** ;**** THIS IS THE NORMAL READ ROUTINE. THE ACC **** ;**** HAS THE NUMBER OF SECTORS TO BE READ. REG B **** ;**** CONTAINS THE DESIRED TRACK, REGISTER C HAS **** ;**** THE DESIRED DRIVE AND REGISTER D CONTAINS THE **** ;**** DESIRED SECTOR (0-9) WITHIN THE TRACK. THE **** ;**** DATA WILL BE LOADED BEGINNING AT H,L. TRAK2 **** ;**** AND TRAK3 ARE INITIALIZED FROM THE DISK TO 59H **** ;**** WHEN THE 1ST BLOCK IS READ IN; THE TEST FOR **** ;**** OLD TRK=59H IS REQD IN MULTIPLE DRIVE SYSTEMS **** ;**** WHERE THE 2ND & 3RD DRIVES MAY BE UNINITIALIZED**** ;**** FOR SOME TIME AFTER THE SYSTEM 1ST COMES UP. **** ;******************************************************** LE91E PUSH PSW PUSH H PUSH D PUSH B MVI B,BRD+3 ;CMNDS START AT 0EBH (C = 01H) CALL MOTON ;MOTOR ON, SEL DRIVE, LOAD HEAD LXI H,DOS-(BOARD+300H)-1 DAD B ;H = DOS + SELECTED DRIVE (1-3) MOV A,M ;GET CURRENT TRACK ADDRESS XRI 59H ;STARTUP INIT. ALL 3 TO 59H PUSH H CZ LE964 ;WILL POSITION HEAD TO TRK 0 POP H POP PSW ;PUSHED AS B - DESIRED TRACK CALL LE964 ;POSITN HEAD TO TRK IN A POP B ;PUSHED AS D - DESIRED SECTOR ;******************************************************** ;**** THIS ROUTINE WAITS UNTIL WE HAVE THE DESIRED **** ;**** SECTOR AND THEN JUMPS TO EITHER 200AH OR 2007H **** ;**** OR FALLS THRU TO READ DATA DEPENDING ON REG C **** ;**** WHICH IS THE COMMAND (0=WRITE, 1=READ, 2=VER) **** ;******************************************************** LE938 CALL LE9CE ;WAIT FOR SECTOR FLAG LDA BSTAT ;GET SECTOR POSITION ANI SCTPS ;MASK IT CMP B ;IS IT THE ONE WE WANT? JNZ LE938 ;NO--WAIT FOR NEXT SECTOR POP H ;PUSHED AS H-DATA LOAD ADDRESS DCR C ;TO SET COMMAND FOR PROPER JUMP JM BOARD+0AH ;RETURN FOR WRITE ROUTINE JNZ BOARD+7H ;RETURN FOR VERIFY ROUTINE ;******************************************************** ;**** THIS ROUTINE WAITS UNTIL IT IS TIME TO READ **** ;**** AND THEN JUMPS TO THE ACTUAL READ ROUTINE. IF **** ;**** A SYNC CHARACTER HAS NOT BEEN DETECTED WITHIN **** ;**** A SPECIFIED TIME FOLLOWING A SECTOR HOLE, THEN **** ;**** THEN ACC IS SET NON-ZERO AND A JUMP TO AN ERROR**** ;**** ROUTINE IS MADE. **** ;******************************************************** LE94C MVI B,8CH ;MAX DELAY SECTOR TO SYNC CHAR LXI D,RDATA ;SET UP D TO READ ACTUAL DATA MVI C,0 LE953 LDA ASTAT ;LOAD A STAT INTO ACC ANI SYNCF ;SYNC CHAR FOUND-RDY TO READ JNZ READ ;TO DO ACTUAL READ DCR B ;WAIT SOME MORE JNZ LE953 ;WE HAVEN'T REACHED LIMIT YET MVI A,01H ;WE'RE IN TROUBLE JMP LE9AB ;JUMP TO ERROR ROUTINE ;******************************************************** ;**** THIS IS THE TRACK SELECT ROUTINE. ENTER WITH **** ;**** DESIRED TRACK IN A AND H,L POINT TO CURRENT **** ;**** TRACK. IT LOADS H,L WITH A DIRECTION SETTING **** ;**** ADDRESS AND PUTS NO OF STEPS REQD IN REG C. **** ;******************************************************** LE964 MOV D,A ;SAVE DESIRED TRACK SUB M ;SUBTRACT PRESENT TRACK MOV M,D ;STORE NEW TRACK ADDRESS RZ ;DONE IF OLD ADDR=NEW ADDR LXI H,STPIN ;LOAD H STEP DIR 'IN' MOV C,A ;DIFFERENCE IS NO OF STEPS REQD JP LE97B ;GO STEP IT CMA ;DIFF WAS NEG--NEED TO STEP OUT INR A ;INVRT THE NEG NO OF STEPS REQD MOV C,A ;NO OF STEPS 'OUT' REQD IN C LDA ASTAT ;ALREADY ALL THE WAY OUT? ANI TRAK0 ;TRACK 0 FLAG RNZ ;YES--CAN'T GO OUT ANY FURTHER LXI H,STPOU ;LOAD H STEP DIR 'OUT' ;******************************************************** ;**** THIS ROUTINE ACTUALLY DOES THE HEAD STEPPING. **** ;******************************************************** LE97B MOV A,M ;SET DIR FF AS PER H REG LE97C LDA SETFF ;SET TRACK STEP FF XTHL ;SHORT TIME DELAY XTHL ;MORE DELAY (MIN 10 USEC TOTAL) LDA RESFF ;RESET TRACK STEP FF MVI D,02H ;WAIT 2 SECTOR TIMES (40 MSEC) CALL DELAY LDA ASTAT ;FIND OUT WHERE WE'RE AT ANI TRAK0 ;TRACK ZERO? JZ LE993 ;JUMP IF NOT TRACK 0 MVI C,01H ;WERE ALL WAY OUT-SET C TO STOP LE993 DCR C ;NEED MORE STEPS? JNZ LE97C ;YES--CONTINUE STEPPING RET ;NO--WERE DONE, RETURN. ;******************************************************** ;**** THIS IS THE ERROR ROUTINE FOR THE BOOTSRAP ONLY**** ;******************************************************** CKBS POP B ;B IS CONDITION CODE JZ BOARD+4H ;OK--JMP TO LOADED 1ST BLOCK DCR B ;IF HARD ERROR, TRY 10 TIMES JNZ LE905 ;TRY AGAIN DIE JMP DIE ;HARD ERROR IN BS, NO RECOVERY NOP NOP NOP NOP NOP NOP NOP NOP ;******************************************************** ;**** THIS SETS UP B FOR HANDLING BY THE ERR ROUTINE **** ;**** POPS STACK & 0'S REG A SO CKBS WILL DET ERROR **** ;******************************************************** LE9AB POP B ORA A RET ;******************************************************** ;**** THIS IS THE ACTUAL DATA READ ROUTINE. **** ;******************************************************** READ MOV B,C ;MOVE 0 TO B READ1 LDAX D ;THIS IS THE ACTUAL DATA READ MOV M,A ;STORE DATA IN MEMORY XRA B ;I THINK THIS ADDS TO CKSUM RLC ;THIS TOO MOV B,A ;MOVE PARTIAL CKSUM TO B INX H ;SET H FOR NEXT BYTE DCR C ;GOING TO READ 256 BYTES & CKSUM JNZ READ1 ;READ MORE DATA LDAX D ;READ THE CHECKSUM FROM DISK XRA B ;COMPARE IT WITH CALCULATED CKSUM JZ LE9C4 ;IF THEY ARE SAME GO ON MOV A,B ;?--CAN'T FIGURE THIS ONE OUT MVI A,02H ;SET A NON-ZERO TO DETECT ERROR JMP LE9AB ;JUMP TO THE ERROR HANDLER LE9C4 POP PSW ;GET NO OF SECTORS TO BE READ DCR A ;DECREMENT IT RZ ;RETURN IF DONE PUSH PSW ;SAVE IT CALL LE9CE ;WAIT FOR SECTOR HOLE JMP LE94C ;WAIT FOR SYNC & READ NXT SECTR ;******************************************************** ;**** DELAY ROUTINE; DELAY IS NO OF SECTOR TIMES IN **** ;**** THE D REGISTER. **** ;******************************************************** LE9CE MVI D,01H ;HERE TO RET WHEN SCTR FOUND DELAY LDA RSFLG ;RESET SECTOR FLAG TSTSF LDA ASTMS ;LOAD A STATUS REG TO ACC ANI 80H ;MASK SECTOR FLAG JZ TSTSF ;TEST SECTOR FLAG DCR D RZ ;IF ZERO WE'RE DONE JMP DELAY ;GIVE IT MORE TIME ;******************************************************** ;**** THIS ROUTINE STARTS THE MOTOR, WAITS 5 REV (50 **** ;**** SECTOR TIMES) FOR IT TO COME UP, LOADS HEAD & **** ;**** DRIVE SELECT REG (USING CONTENTS OF C REGISTER)**** ;**** STORES SELECTED DRIVE AT 2003H & DELAYS 13 **** ;**** SECTOR TIMES FOR HEAD TO SETTLE FROM LOAD. **** ;**** IF MOTOR WAS ALREADY ON, CHECKS DRIVE CURRENTLY**** ;**** SELECTED (2003H) VS DRIVE REQUESTED IN REG C **** ;**** IF THEY ARE SAME, SKIPS HEAD LOAD SETTLE DELAY.**** ;**** ON ENTRY, C=DESIRED DRIVE, B=0EBH. **** ;******************************************************** MOTON LDA ASTMS ;LOAD A STAT & START MOTOR ANI MOTST ;MASK MOTOR ON TEST BIT JNZ CKDRV ;JUMP IF MOTOR ON MVI D,32H ;5 REV TO SPEED UP CALL DELAY JMP LHSD ;LOAD HEAD & SELECT DRIVE CKDRV LDA DRSEL ;GET DRIVE CUR SELECTED IN ACC CMP C ;C HAS DRIVE WE WANT--SAME? RZ ;YES--HEAD IS LOADED, SKIP DELAY LHSD LDAX B ;LOAD HEAD & DR SEL REG USING C MOV A,C ;MOVE SELECTED DRIVE TO ACC STA DRSEL ;STORE IT MVI D,0DH ;SETTLE TIME FROM HEAD LOAD JMP DELAY DEFST ORG DOS TRAK1 DS 1 ;STORE HEAD LOC (TRACK) DRIVE #1 TRAK2 DS 1 ;STORE HEAD LOC (TRACK) DRIVE #2 TRAK3 DS 1 ;STORE HEAD LOC (TRACK) DRIVE #3 DRSEL DB 1 ;DRIVE CURRENTLY SELECTED LEVL2 JMP DOS+5AH ;ENTRY TO 2ND LEVEL BOOT VERFY JMP DOS+75FH ;RE-ENTRY TO VERIFY ROUTINE WRITE JMP DOS+78EH ;RE-ENTRY TO WRITE ROUTINE ;PAGE ;********************************************************* ;**** THE NORTH STAR DOS AS DIS-ASSEMBLED BY BARRY A. **** ;**** WATZMAN, CCP, CDP. COPYRIGHT 1977 BY NORTH **** ;**** STAR COMPUTERS AND BARRY A. WATZMAN. **** ;********************************************************* ;**** THE MAIN DOS STARTS HERE. **** ;********************************************************* BOARD EQU 0E800H ;LOCATION OF NORTH STAR BOARD BRD EQU 0E8H ;HIGH ORDER BYTE OF BOARD DOS EQU 2000H ;ADDR OF DOS LE91E EQU BOARD+11EH ;READ ROUTINE IN PROM BOOTSTRAP LE9CE EQU BOARD+1CEH ;RETURN ON NEXT SCTR FOUND FLAG LEB90 EQU BOARD+390H ;LOAD A STAT REG & START MOTOR LE9D0 EQU BOARD+1D0H ;SECTOR BASED DELAY ROUTINE LEB10 EQU BOARD+310H ;LOAD A STATUS REG LE9AB EQU BOARD+1ABH ;ERROR HNDLER IN PROM BOOTSTRAP LEB04 EQU BOARD+304H ;START A WRITE SECTOR SEQUENCE NCOM EQU 15 ;NO OF ENTRIES IN COMD TABLE ORG DOS TRAK1 DB 0 ;CUR TRK LOCATION OF HEAD DR #1 TRAK2 DB 59H ;SAME DR #2 TRAK3 DB 59H ;SAME DR #3 DRSEL DB 1 ;DRIVE CURRENTLY SELECTED BOOT2 JMP STACK ;ENTRY TO 2ND LEVEL BOOTSTRAP JMP L275F ;VERIFY ROUTINE L200A JMP L278E ;WRITE ROUTINE COUT JMP COUT ;REPL W JMP TO CHAR OUT ROUTINE CIN JMP CIN ;REPL W JMP TO KYBD INP ROUTINE TINIT JMP TINIT ;REPL W JMP TO INIT ROUT IF ANY CONTC JMP CONTC ;REPL W JMP TO CNTL C ROUTINE HDERR JMP DSKER ;HARD DISK ERROR ROUTINE DLOOK JMP L2399 ;DIRECTORY LOOKUP ROUTINE DWRIT JMP L240E ;DIRECTORY WRITE ROUTINE DCOM JMP DCOMD ;TO ISSUE DISK COMMAND LIST JMP LICMD+3 ;DIRECTORY LIST ROUTINE BEGIN JMP START ;ENTRY FOR LOADED DOS RWCHK DB 0 ;READ AFTR WRIT CK IF 1 DS 46 ;RESERVED FOR STACK ;********************************************************** ;**** 2ND LEVEL BOOT LOADS DISK ADDRS. 5-13 AT 2100H. **** ;********************************************************** STACK LXI SP,STACK MVI A,5 ;5 BLKS LXI B,1 ;TRACK 0 DRIVE 1 LXI D,0501H ;SECTOR 5, READ LXI H,DOS+100H ;PUT THEM AT 2100H (STD VER) CALL LE91E ;DO IT JNZ STACK ;ON ERROR(?) MVI A,4 ;4 BLKS LXI B,0101H ;TRACK 1, DRIVE 1 LXI D,1 ;SECTOR 0, READ LXI H,DOS+600H ;PUT THEM AT 2600H (STD VER) CALL LE91E ;DO IT JNZ STACK ;ON ERROR(?) CALL TINIT ;START MAIN DOS ;********************************************************** ;**** MAIN DOS STARTS HERE. **** ;********************************************************** START LXI SP,STACK ;SET STACK LXI H,DOS+0B7H ;?--DOES NOT SEEM NECESSARY SHLD HDERR+1 MVI B,'*' ;GET THE PROMPT CALL PRINT ;PRINT IT CALL GETLN ;GET A COMMAND LINE FROM INPUT LXI H,LNBUF ;POINT H,L TO COMMAND CALL LDDEM ;LOAD IT TO D,E LXI H,CMDTB ;POINT H,L TO COMMAND TABLE MVI B,NCOM ;B HAS NO OF COMMANDS IN TABLE TYNXT CALL COMPR ;LOOK FOR MATCH INX H ;TO ADDR FOR COMD JUST TESTED INX H JZ DOIT ;COMMANDS MATCHED--SET IT UP INX H ;NO MATCH-POINT TO NXT COMMAND INX H DCR B ;DCR NO OF COMDS LEFT TO TEST JNZ TYNXT ;NOT DONE-TEST NEXT COMMAND WHAT MVI B,'?' ;OPPS-NONE OF COMDS MATCHED CALL PRINT CRLFR CALL CRLF JMP START ;********************************************************** ;**** HARD DISK ERROR ROUTINE. C=DRIVE NO.; B=TRACK; **** ;********************************************************** DSKER PUSH D PUSH B MOV A,C ;GET DRIVE ADI 30H ;CONVERT TO ASCII MOV B,A CALL PRINT CALL PSPAC ;PRINT DRIVE FOLLOWED BY SPACE POP B MOV L,B ;SET TRACK (0-34) IN H,L MVI H,0 CALL TDDPT ;TWO DIGIT DECIMAL PRT ROUTINE POP D LXI H,DOS+7BFH LDA L27BE SUB M ADD D ADI 30H ;CONVERT TO ASCII MOV B,A CALL PRINT MVI B,'H' CALL PRINT MVI B,'D' CALL PRINT JMP WHAT ;********************************************************** ;**** ROUTINE TO JMP TO COMMAND ADDR & COMMAND TABLE. **** ;********************************************************** DOIT CALL LDDEM ;GET CMND ADDR IN D,E XCHG ;TO H,L LXI D,START PUSH D ;SET UP SO RET RESTARTS DOS PCHL ;DO IT CMDTB DB 'CR' DW CRCMD DB 'DE' DW DECMD DB 'GO' DW GOCMD DB 'JP' DW JPCMD DB 'RD' DW RDCMD DB 'WR' DW WRCMD DB 'DT' DW DTCMD DB 'IN' DW INCMD DB 'LI' DW LICMD DB 'TY' DW TYCMD DB 'LF' DW LFCMD DB 'SF' DW SFCMD DB 'CF' DW CFCMD DB 'CD' DW CDCMD DB 'CO' DW COCMD ;********************************************************** ;**** DELETE COMMAND. ERASES FILE NAME IN DIRECTORY. **** ;********************************************************** DECMD CALL L23B1 ;GET NAME, DRIVE, DO LOOKUP CALL L2750 ; ? CALL L2404 ;PUT SPACES IN FILE-NAME BUFFER JMP L240E ;WRITE DIRECTORY BLK BACK TO DISK ;********************************************************** ;**** LIST COMMAND (LIST DISK DIRECTORY). **** ;********************************************************** LICMD CALL GTDRV ;GET UNIT IF SPECIFIED STA L28EE ;DRIVE IN ACC FOR EXTERNAL LISTS MVI A,1 ;1=LIST COMMAND JMP L250D ;DO IT ;********************************************************** ;**** JPCMD. JUMP (EXEC) COMMAND. **** ;********************************************************** JPCMD CALL HXBIN ;CONVERT ADDRESS TO BIN IN H,L CALL L2750 ;MAKE SURE IT IS END OF INPUT LINE PCHL ;GO TO IT ;********************************************************** ;**** GO COMMAND. LOADS FILE & JUMPS TO GO ADDRESS. **** ;********************************************************** GOCMD CALL L23B1 ;GET NAME, DRIVE & DO DIR LOOKUP MOV C,A ;DRIVE TO REG C CALL L2750 ; ? CALL LDDEM ;GET DISK ADDRESS PUSH D ;PUSH IT CALL LDDEM ;GET DISK LENGTH MOV A,M ;GET TYPE INX H ;POINT TO GO ADDRESS CPI 1 ;TYPE = 1 ? JNZ WHAT ;NO--REPORT ERROR MOV A,E ;YES--LENGTH TO A (NOTE 256 MAX) CALL LDDEM ;GET GO ADDRESS POP H ;DISK ADDRESS TO H,L PUSH D ;PUSH GO ADDR SO FINAL RET JMPS MVI B,1 ;1=READ JMP DCOMD ;DO THE READ ;********************************************************** ;**** TYPE COMMAND. ADDS TYPE & GO ADDR TO DIR ENTRY **** ;********************************************************** TYCMD CALL L23B1 ;GET NAME, DRIVE & DO DIR LOOKUP LXI D,4 ;SET UP TO POINT TO TYPE BYTE DAD D PUSH H ;SAVE POINTER CALL DCBIN ;CONVERT DECIMAL TYPE TO BINARY JC WHAT ;IF TYPE KEYED IN NOT LEGAL MOV A,L ;BINARY TYPE TO ACC POP H ;GET BACK POINTER MOV M,A ;CHANGE TYPE CPI 1 ;TYPE = 1 (EG, NEED GO ADDR) ? JNZ L2189 ;NO--WRITE DIRECTORY BLK BACK PUSH H ;SAVE POINTER CALL HXBIN ;CONVERT ASCII HEX GA TO BINARY XCHG ;MOVE IT TO D,E POP H ;GET BACK POINTER INX H ;POINT TO GO ADDRESS CALL LDMDE ;PUT NEW GA (D,E) THERE L2189 CALL L2750 ;END OF COMMAND ? JMP L240E ;YES--WRITE UPDATD DIR BACK TO DSK ;********************************************************** ;**** CF (COPY FILE) COMMAND. **** ;********************************************************** CFCMD CALL L23B1 LDA L28EE STA LNBUF CALL LDDEM PUSH D CALL LDDEM PUSH D CALL LDDEM PUSH D CALL LDDEM PUSH D CALL L23B1 CALL L2750 LXI B,7 DAD B POP B MOV M,B DCX H MOV M,C POP B DCX H MOV M,B DCX H MOV M,C DCX H DCX H POP D PUSH D DCX D CALL COMPR JNC WHAT DCX H MOV D,M DCX H MOV E,M PUSH D CALL L240E POP H POP B POP D JMP L234F ;********************************************************** ;**** LF & SF (LOAD FILE / SAVE FILE) COMMANDS. **** ;********************************************************** LFCMD MVI B,1 ;1 = READ COMMAND JMP L21DB SFCMD MVI B,0 ;0 = WRITE COMMAND L21DB PUSH B ;SAVE COMMAND CALL L23B1 ;GET FILENAME, UNIT, DO LOOKUP POP B ;GET BACK COMMAND LDA L28EE ;GET DRIVE MOV C,A ;TO REG C PUSH B ;SAVE COMMAND CALL LDDEM ;GET DISK ADDRESS PUSH D ;SAVE IT CALL LDDEM ;GET DISK LENGTH MOV A,E ;MOVE IT TO ACC. PUSH PSW ;SAVE DISK LENGTH CALL HXBIN ;CONVERT LOAD ADDR TO BIN IN HL XCHG ;MOVE IT TO D,E CALL L2750 ;MAKE SURE IT'S END OF COMMAND POP PSW ;GET BACK DISK LENGTH POP H ;GET BACK DISK ADDRESS POP B ;GET BACK COMMAND & UNIT L21F8 CALL DCOMD ;DO IT JC WHAT ;ON ERROR RET ;DONE ;********************************************************** ;**** RD & WR (READ & WRITE SINGLE BLOCK) COMMANDS. **** ;********************************************************** RDCMD MVI B,1 ;1 = READ COMMAND JMP L2206 WRCMD MVI B,0 ;0 = WRITE COMMAND L2206 CALL DCBIN ;GET DISK ADDR TO R/W IN H,L JC WHAT ;ON ERROR PUSH H ;SAVE DISK ADDRESS MVI C,1 ;SET DEFAULT UNIT CPI ' ' ;SEE IF SPACE FOLLOWS DISK ADDR JZ L221C ;YES--GET RAM ADDRESS CPI ',' ;NO--DOES COMMA FOLLOW DISK ADDR? JNZ WHAT ;ONLY ' ' & ',' MAY FOLLOW D.A. CALL GTDRV ;COMMA FOLLOWS D.A.--GET DRIVE L221C CALL HXBIN ;CNVRT HEX ADDR TO BIN IN HL PUSH H ;SAVE IT CALL DCBIN ;CONVERT NO. OF BLOCKS TO BINARY MOV A,L ;MOVE IT TO ACC (256 MAX) POP D ;GET BACK RAM ADDRESS POP H ;GET BACK DISK ADDRESS JMP L21F8 ;DO IT ;********************************************************** BLKBF DS 8 ;BLANK FILE-NAME ;********************************************************** ;**** CR (CREATE FILE) COMMAND. **** ;********************************************************** CRCMD CALL L23BB ;GET DRIVE #, FILE NAME CALL L250C ;LOOK UP FILE NAME JNC WHAT ;IF IT ALREADY EXISTS PUSH H ;ADDRESS OF 1ST FREE BLOCK LXI D,BLKBF ;PTR TO BLANKED OUT FILE NAME AREA CALL L250C ;FIND 1ST BLANK DIR ENTRY JC WHAT ;IF NONE EXISTS XTHL ;1ST FREE TO HL, DIR PTR TO STACK PUSH H ;PUSH 1ST FREE BLOCK CALL DCBIN ;GET LENGTH JC WHAT ;LENGTH MISSING OR INVALID XTHL ;LEN TO STACK TOP, HL=1ST FREE BLK CALL DCBIN ;REPL HL WITH ADDR IN CMD IF ANY CALL L2750 ;END OF COMD REQD XCHG ;START ADDR TO D,E LXI H,-351 ;SET UP TO TEST LENGTH, START ADDR POP B ;GET LENGTH DAD B ;ADD TO -MAX LENGTH JC WHAT ;IF TOO LONG DAD D ;ADD STARTING ADDR JC WHAT ;IF NOT ENOUGH ROOM LEFT ON DISK POP H ;GET POINTR TO 9TH BYTE IN RAM DIR PUSH H ;PUT IT BACK CALL LDMDE ;PUT START ADDR IN RAM DIR ENTRY MOV M,C ;MOVING LENGTH TO RAM DIR ENTRY INX H ;CONTINUED MOV M,B ;CONTINUED INX H ;CONTINUED MVI M,0 ;DEFAULT TYPE POP H ;POINT BACK TO END OF NAME LXI D,DOS+8EDH ;DE POINT TO END OF NAME BUFFER MVI B,8 ;NO OF CHAR IN FILE NAME L2271 DCX H ;MOVING NAME TO RAM DIR ENTRY LDAX D ;CONTINUED MOV M,A ;CONTINUED DCX D ;CONTINUED DCR B ;CONTINUED JNZ L2271 ;IF NOT DONE JMP L240E ;WRITE DIRECTORY BACK TO DISK ;********************************************************** ;**** CO (COMPRESS DISKETTE) COMMAND. **** ;********************************************************** COCMD CALL GTDRV STA LNBUF CALL L2750 LXI H,4 L2288 PUSH H MVI A,2 CALL L250D JC L229B INX H INX H CALL LDDEM POP H DAD D JMP L2288 L229B POP D LDA L28F1 ORA A RNZ LHLD L28F4 PUSH H PUSH D MVI A,2 CALL L250D POP D PUSH D CALL LDMDE CALL LDDEM PUSH D CALL L240E POP B POP H POP D PUSH H DAD B XTHL CALL L234F POP H JMP L2288 ;********************************************************** ;**** IN (INITIALIZE BLANK DISKETTE) COMMAND. **** ;**** THE "INCREMENT" IS FOR THE DT COMD & IS 0 HERE. **** ;********************************************************** INCMD CALL GTDRV ;GET THE DRIVE CALL L2750 ;MAKE SURE IT'S END OF COMMAND LXI H,2000H ;20=INITLZATION CHAR; 00=INCREMENT SHLD LNBUF ;SAVE THEM L22D0 MVI B,0 ;0=WRITE COMMAND L22D2 LDA L28EE ;GET THE DRIVE MOV C,A ;MOVE IT TO REG C MVI A,35 ;NO OF TRACKS ON DISK LXI H,0 ;STARTING DISK ADDRESS L22DB PUSH PSW ;SAVE NO TRACKS LEFT TO DO PUSH B ;SAVE COMMAND & UNIT PUSH H ;SAVE STARTING DISK ADDRESS LHLD LNBUF ;GET INIT CHAR & INCREMENT MOV A,H ;INITIALIZATION CHAR TO ACC. LXI D,DOS+1400H ;TOP OF RAM SCRATCH AREA LXI B,0A00H ;LENGTH OF RAM SCRACTH AREA L22E8 DCX D ;DCR POINTER STAX D ;MOVE INIT CHAR TO DE POINTER DCR C ;DCR NO OF CHAR LEFT IN BLOCK JNZ L22E8 ;CONTINUE IF NOT DONE WITH BLOCK ADD L ;DONE W BLOCK; INR INIT CHAR. MOV H,A ;SAVE NEW INIT CHAR DCR B ;DCR NO OF BLOCKS LEFT TO DO JNZ L22E8 ;DO NEXT BLOCK UNLESS DONE SHLD LNBUF ;SAVE INIT CHAR & INCREMENT POP H ;GET DISK ADDRESS POP B ;GET UNIT & COMMAND PUSH B ;PUT THEM BACK PUSH H ;SAVE DISK ADDRESS MVI A,10 ;10 BLOCKS/TRACK & IN CORE CALL DCOMD ;WRITE THEM OUT JC WHAT ;ON ERROR CALL CONTC ;CHECK FOR ABORT JZ WHAT ;FOUND--ABORT IT POP H ;GET DISK ADDRESS LXI B,000AH ;WE JUST DID 10 BLOCKS DAD B ;INR DISK ADDRESS POP B ;RESTORE COMMAND & UNIT POP PSW ;RESTORE NO OF LEFT TO DO DCR A ;DCR NO OF TRACKS LEFT TO DO JNZ L22DB ;DO NEXT TRACK IF NOT DONE RET ;DONE ;********************************************************** ;**** DT (DISKETTE TEST) COMMAND. **** ;********************************************************** DTCMD CALL GTDRV CALL L2750 LXI H,1 SHLD LNBUF L2321 CALL L22D0 LXI H,LNBUF+1 MOV A,M SUI 5EH MOV M,A MVI B,2 CALL L22D2 JMP L2321 ;********************************************************** ;**** CD (COPY DISKETTE) COMMAND. **** ;********************************************************** CDCMD CALL GTDRV STA LNBUF CALL FTCHR CPI ' ' JNZ WHAT CALL GTDRV CALL L2750 LXI B,015EH LXI H,0 MOV D,H MOV E,L L234F SHLD LNBUF+1 XCHG SHLD LNBUF+3 LXI H,0FFF6H DAD B JNC L2373 PUSH H MVI A,0AH CALL L2376 LXI B,000AH LHLD LNBUF+3 DAD B XCHG LHLD LNBUF+1 DAD B POP B JMP L234F L2373 MOV A,C ORA A RZ L2376 PUSH PSW LHLD LNBUF MOV C,L LHLD LNBUF+3 LXI D,DOS+0A00H PUSH D MVI B,1 CALL DCOMD LHLD LNBUF+1 POP D LDA L28EE MOV C,A MVI B,0 POP PSW CALL DCOMD JC WHAT RET ;********************************************************** ;**** THIS ROUTINE DOES DIRECTORY LOOKUPS. ON ENTRY **** ;**** H,L POINT TO NAME TO BE LOOKED UP, A HAS DRIVE. **** ;********************************************************** L2399 SHLD CLPTR ;STORE POINTER TO NAME TO LOOK UP STA L28EE ;STORE REQUESTED DRIVE MOV A,M ;GET 1ST CHAR OF NAME TO LOOK UP CPI ' ' ;LOOKING FOR AN EMPTY ENTRY ? JNZ L23AB ;NO--LOAD BUFFER,DO LOOKUP CALL L2401 ;YES--BLANK BUFFER JMP L23AE ;DO LOOKUP L23AB CALL L23C0 ;LOAD BUFFER FROM INPUT LINE L23AE JMP L250C ;DO DE/CR TYPE LOOKUP ;********************************************************** ;**** BLANK OUT FILE-NAME BUFFER, GET FILE NAME, **** ;**** DRIVE, DO DIRECTORY LOOKUP. **** ;********************************************************** L23B1 CALL L23BB ;GET DRIVE, FILE NAME CALL L250C ;DO LOOKUP JC WHAT ;IF ERROR DETECTED RET L23BB MVI A,1 ;DRIVE #1 = DEFAULT STA L28EE ;STORE IT AS SELECTED DRIVE L23C0 CALL L2401 ;BLANK OUT BUFFER & POINT TO START PUSH H ;SAVE PTR TO FILE NAME BUFFER L23C4 CALL FTCHR ;GET CHAR FROM INPUT LINE JZ L24BF ;STC & RETURN IF 1ST CHAR = CR CPI ' ' ;1ST CHAR = SPACE ? JZ L23C4 ;YES--GET NEXT CHAR CPI ',' ;1ST CHAR = ',' ? JZ L24BF ;STC & RET; , NOT ALLOWED HERE MVI B,8 ;GOT LIVE CHAR--SET NAME LENGTH L23D6 JZ L23FF ;CHAR WAS C/R; DONE WITH NAME CPI ' ' ;WAS CHAR SPACE ? JZ L23FF ;YES--DONE WITH NAME CPI ',' ;WAS CHAR ',' ? JZ L23EF ;YES--GET SPECIFIED DRIVE DCR B ;NORM CHAR; DCR COUNT OF CHR LEFT JM L24BF ;JMP IF DONE WITH 8 CHAR NAME MOV M,A ;STORE CHAR IN BUFFER INX H ;INR NAME BUFFER POINTER CALL FTCHR ;GET THE NEXT CHAR JMP L23D6 ;PROCESS IT L23EF CALL GTDRV ;GET THE SPECIFIED DRIVE CALL FTCHR ;GET THE NEXT CHAR CPI ' ' ;SPACE ? JZ L23FF ;YES--DONE CPI 0DH ;NO--C/R ? JNZ L24BF ;NO--INVALID CHAR TYPED; STC & RET L23FF POP D ;RESTORE PTR TO FILENAME BUF TO D RET ;********************************************************** ;**** THIS ROUTINE BLANKS OUT A FILE NAME BUFFER AT **** ;**** 28E6H TO 28EDH USED TO HOLD FILE NAMES. **** ;********************************************************** L2401 LXI H,DOS+8EEH ;LOAD 1 PAST END OF BUFFER L2404 MVI B,8 ;SET BUFFER LENGTH L2406 DCX H ;DCR BUFFER POINTER MVI M,' ' ;PUT SPACE IN BUFFER DCR B ;DCR COUNT OF CHAR LEFT JNZ L2406 ;IF NOT DONE RET ;********************************************************** ;**** THIS ROUTINE WRITES AN UPDATED DIRECTORY BLOCK **** ;**** BACK TO THE DISK. **** ;********************************************************** L240E LDA L28EE ;GET DRIVE MOV C,A ;TO REG C LDA L28F0 ;LOW ORDER DISK ADDRESS MOV L,A ;TO REG L MVI H,0 ;HIGH ORDER DISK ADDR MVI B,0 ;0=WRITE COMMAND LXI D,AREA ;CORE ADDR OF BLK TO BE WRITTEN MVI A,1 ;JUST 1 BLOCK CALL DCOMD ;DO IT JC WHAT ;IF ERROR RET ;********************************************************** L2426 MOV A,E ORA A JNZ L245A LDA RWCHK ORA A JZ L245A POP H POP PSW LDA L27BE MVI E,2 L2439 STA L27BE MVI A,0AH L243E PUSH PSW PUSH H PUSH D PUSH B LDA L27BE CALL LE91E MOV A,B STA L27BF POP B POP D JZ L2426 POP H POP PSW DCR A JNZ L243E JMP HDERR L245A POP D POP D JMP LE9CE ;NSDOS2 3000 9073 2770 11/06/77 ;********************************************************** ;**** DISK COMMAND ROUTINE. ACC = NO. BLOCKS; **** ;**** B = COMMAND (0=WRITE, 1=READ, 2=VRFY), C = UNIT **** ;**** DE = STARTING RAM ADDR., HL = DISK ADDR. **** ;**** RETURN WITH CARRY SET IF ARGS ARE ILLEGAL. **** ;********************************************************** DCOMD PUSH D ;SAVE REGISTERS PUSH B PUSH PSW PUSH H ORA A ;NO BLOCKS = 0 ? JZ L24BC ;YES - ERROR LXI D,-350D ;NO - CHECK VALU OF DISK ADDR. DAD D ;ADD REQ. STARTING DISK ADDR JC L24BC ;IF START ADDR > 349 MOV E,A ;NO BLOCKS TO E MVI D,0 DCX D DAD D ;ADD NO BLOCKS TO START ADDR JC L24BC ;IF RESULT > 349 MOV A,C ;UNIT NO. CPI 1 ;MUST BE 1,2 OR 3 -- NOT 0 JC L24BC ;IF ERROR CPI 4 ;MUST NOT BE > 3 JNC L24BC ;IF ERROR MOV A,B ;COMMAND CPI 1 ;READ ? JZ L24C2 ;YES - GO TO READ ROUTINE CPI 2 ;VERIFY ? JZ L24C2 ;YES-GO TO VERYIFY/READ ROUTINE CPI 0 ;WRITE ? JNZ L24BC ;NO - ERROR IF NOT 0,1 OR 2 LDA LEB90 ;LOAD A STAT & START MOTOR ANI 10H ;MOTOR ON ? JNZ L24A1 ;YES - JUMP MVI D,50 ;NO-SET UP 50 SECTOR HOLE DELAY CALL LE9D0 ;WAIT JMP L24A8 L24A1 LDA DRSEL ;FIND OUT WHICH DRIVE SEL. CMP C ;THE ONE WE WANT ? JZ L24B4 ;YES L24A8 MVI B,BRD+3 ;SET UP HD. LOAD & DRIVE LDAX B ;LOAD HEAD & SELECT MOV A,C ;GET SELECTED DRIVE STA DRSEL ;STASH SELECTED DRIVE MVI D,13 ;SET UP DELAY FOR SETTLE TIME CALL LE9D0 ;WAIT L24B4 LDA LEB10 ;LOAD A STAT REG ANI 2 ;WRITE PROTECT ? JZ L24C2 ;JUMP IF NOT L24BC POP H ;ELSE ERROR RETURN POP PSW POP B L24BF POP D STC RET L24C2 POP H ;GET DISK ADDR BACK POP PSW ;GET NO BLOCKS BACK LXI D,-10 MVI B,0FFH ;0FFH = -1 L24C9 INR B ;KEEP A COUNT OF "ADDITIONS" DAD D ;SUBTRACT 10 FROM DISK ADDR JC L24C9 ;DO IT AGAIN IF ANS > 0 L24CE ADD L ;GET STARTING SECTOR (?) ;********************************************************** ;**** NOTE THAT THE FOLLOWING INST WAS ORIGINALLY A **** ;**** JM (FA) RATHER THAN A JNC (D2). THIS PREVENTED **** ;**** THE DOS FROM WORKING WITH FILES > 134 BLOCKS. **** ;********************************************************** JNC L24FE JZ L24FE MOV H,A MOV A,L ADI 10 MOV D,A SUI 0BH CMA STA L27BF MOV L,B SHLD L28E0 POP H SHLD L28E2 MOV C,L MOV E,H POP H CALL L2439 PUSH H LHLD L28E2 PUSH H LHLD L28E0 MOV A,H MOV B,L INR B MVI L,0F6H JMP L24CE L24FE SUB L PUSH PSW MOV A,L ADI 10 MOV D,A POP PSW POP H MOV E,H MOV C,L POP H JMP L2439 ;********************************************************** ;**** THE ROUTINES FROM 250C TO 2625 ARE USED TO READ **** ;**** THE DIRECTORY AND USE IT FOR THE DIRECTORY LIST,**** ;**** COMPRESS AND CREATE COMMANDS. LOOK UP NAMES, **** ;**** GET 1ST FREE BLOCK, 1ST FILE NEEDING COMPR, ETC.**** ;********************************************************** L250C XRA A ;ENTRY PT. FOR CR,DE COMMAND L250D STA L28EF ;SAVE COMD; 0=CR,DE, 1=LI, 2=CO STA L28F1 ;"NEED COMRESSION" FLAG SHLD L28F2 ;1ST "UNCOMPRESSED" FILE BLOCK LXI H,351 ;NO OF DISK BLOCKS + 1 SHLD L28F4 ;D.A. OF LOWEST UNCOMPRESSED FILE LXI H,4 ;LOWEST AVAIL BLK FOR NEW FILE SHLD L28E4 ;1ST FREE BLOCK LXI B,0400H ;NO DIR BLKS, NO CHECKED L2525 XCHG PUSH H ;H POINTS TO NAME TO BE LOOKED UP PUSH B ;NO DIR BLKS, NO CHECKED SO FAR CALL L253B ;TO GET DIR BLK & PROCESS IT POP B ;RESTORE REGESTER POP D ;RESTORE REG-PUSHED AS H AFTR XCHG LDA L28EE ;GET REQUESTED DRIVE BACK IN A RZ ;SET BY PROCESSING ROUTINE IF DONE INR C ;INR DISK ADDR TO BE CHECKED NEXT DCR B ;DCR COUNT OF REMAINING DIR BLOCKS JNZ L2525 ;DO NEXT DIRECTORY BLOCK STC ;ALL BLKS CHECKED & NO MATCH FOUND LHLD L28E4 ;GET 1ST FREE BLOCK IN H,L RET ;TO CALLER L253B PUSH H ;SAVE REG-DIR BLKS CKD, CUR BLOCK MVI H,0 ;HIGH ORDER DISK ADDRESS MOV L,C ;LOW ORDER--DIR BLK TO BE CHECKED LXI D,AREA ;READ WILL STORE DATA BEG AT AREA MOV A,C ;DIRECTORY BLOCK TO BE READ STA L28F0 ;SAVE IT LDA L28EE ;GET THE REQUESTED DRIVE MOV C,A ;MOVE IT TO REG C MVI B,1 ;WE'RE GOING TO READ MVI A,1 ;1 BLOCK CALL DCOMD ;DO READ LXI H,AREA ;POINT TO DOS RAM AREA MVI B,16 ;NO OF DIRECTRY ENTRIES PER BLOCK POP D ;PUSHED AS H; PTR TO NAME TO CHECK L2557 PUSH D ;PUT IT BACK PUSH H ;SAVE PTR TO DIR ENTRY IN DOS RAM MVI C,8 ;FILE NAME IS 8 CHAR LDA L28EF ;GET THE COMMAND ORA A ;SET THE FLAG JNZ L25A2 ;IF IT'S NOT CREATE FILE, JMP ;********************************************************** ;**** THIS ROUTINE COMPARES A NAME POINTED TO BY D,E **** ;**** AGAINST NAMES IN DOS RAM TO SEE IF NAME ALREADY **** ;**** EXISTS. H,L POINT TO DIRECTORY ENTRY IN RAM. **** ;**** ALSO FINDS 1ST FREE ADDR FOR ADDING NEW FILES. **** ;********************************************************** L2562 LDAX D ;POINT TO NAME TO BE MATCHED CMP M ;SAME AS 1ST CHAR OF DIR ENTRY ? JNZ L2571 ;NO-MATCH FAIL OR EMPTY DIR ENTRY INX D ;MATCH--INR POINTER TO NAME INX H ;INR POINTER INTO DIRECT. ENTRY DCR C ;DCR COUNT OF CHAR LEFT TO CHECK JNZ L2562 ;CHECK NEXT CHAR UNLESS DONE L256D POP B ;RESTORE REGISTERS POP B ;RESTORE REGISTERS XRA A ;CLEAR ACCUM. & FLAGS RET ;RET TO CALLER IND. MATCH FOUND L2571 POP H ;GET POINTER INTO RAM DIR ENTRY PUSH H ;PUT IT BACK MOV A,M ;GET 1ST CHAR OF FILE NAME CPI ' ' ;BLANK (E.G. ENTRY EMPTY) ? JZ L2595 ;YES--CHECK NEXT DIRECTORY ENTRY PUSH B ;NO--TRUE MISMATCH; SAVE B REG LXI D,8 ;LOAD D WITH NAME LENGTH DAD D ;POINT TO FILE STARTING DSK ADDR CALL LDDEM ;GET IT TO D,E MOV C,M ;MOVING FILE DISK LENGTH TO B,C INX H ;2ND BYTE MOV B,M ;FILE DISK LENGTH IN B,C XCHG ;MOVE FILE START DISK ADDR TO H,L DAD B ;ADD DSK LNGTH TO DISK START ADDR XCHG ;MOVE RESULT TO D,E LXI H,DOS+8E4H ;GET CURRENT 1ST FREE BLOCK CALL COMPR ;COMPARE IT TO END OF THIS FILE POP B ;RESTORE REGISTER JC L2595 ;IF CUR 1ST FREE>END OF THIS FILE XCHG ;PUT END OF THIS FILE + 1 IN H,L SHLD L28E4 ;UPDATE 1ST FREE BLOCK ;********************************************************** ;**** RESTORES HL TO POINT TO BEG OF CUR DIR ENTRY, **** ;**** INR'S IT BY ENTRY LENGTH & JUMPS TO CHK NEXT **** ;**** ENTRY UNLESS NO ENTRIES LEFT THIS BLOCK; IN **** ;**** WHICH CASE CLEAR FLAGS, SET ACC=1 & RETURN. **** ;********************************************************** L2595 POP H ;GET PNTR TO BEG OF CUR DIR ENTRY LXI D,16 ;LENGTH OF DIRECTORY ENTRY DAD D ;ADD IT TO START OF CUR ENTRY POP D ;POINTER TO NAME TO MATCH DCR B ;MORE ENTRIES TO CHK THIS BLOCK? JNZ L2557 ;YES--SET UP TO CHECK THEM XRA A ;NO-ZERO ACC & CLEAR FLAGS INR A ;PUT 1 IN ACC RET ;RET-TO GET NEXT BLK OR DONE ;********************************************************** ;**** THIS ROUTINE PRINTS A ONE LINE LISTING OF THE **** ;**** DIRECTORY ENTRY IN DOS RAM POINTED TO BY H,L. **** ;**** REG B,C IS PRESERVED & STACK TOP CONTAINS RAM **** ;**** POINTER AT ENTRY ON RETURN. **** ;********************************************************** L25A2 CPI 2 ;IS IT 2 (COMPRESS) ? MOV A,M ;GET CHAR FROM DIRECTY COPY IN RAM JZ L25F8 ;IF COMPRESS JMP CPI ' ' ;IS DIRECTORY ENTRY EMPTY? JZ L2595 ;YES--TRY NEXT DIRECTORY ENTRY PUSH B ;NO-SAVE ENTRIES LEFT & ENTRY LEN L25AE MOV B,M ;GET CHAR OF FILE NAME CALL PRINT ;PRINT IT INX H ;POINT TO NEXT CHAR DCR C ;DCR NO OF CHAR LEFT TO PRINT JNZ L25AE ;IF MORE CHAR LEFT, DO NEXT ONE CALL PSPAC ;SPACE AFTER NAME CALL LDDEM ;GET DISK ADDR IN D,E PUSH H ;SAVE POINTER XCHG ;DISK ADDR TO H,L CALL THDDP ;CALL 3 DIGT DEC PRINT-DSK ADDR CALL PSPAC ;SPACE BETWEEN DSK ADDR & LENGTH POP H ;GET POINTER BACK CALL LDDEM ;GET LENGTH IN D,E PUSH H ;SAVE POINTER XCHG ;LENGTH TO H,L CALL THDDP ;PRINT LENGTH CALL PSPAC ;SPACE AFTER LENGTH POP H ;GET BACK POINTER PUSH H ;SAVE POINTER MOV L,M ;GET TYPE BYTE MVI H,0 ;SINCE TYPE<256 CALL THDDP ;PRINT TYPE POP H ;GET POINTER MOV A,M ;GET TYPE AGAIN CPI 1 ;TYPE 1 FILE ? JNZ L25EB ;NO--DON'T PRINT GO ADDR CALL PSPAC ;YES--SPACE AFTER TYPE INX H ;POINT TO GO ADDR CALL LDDEM ;GET GO ADDR IN D,E XCHG ;MOVE IT TO H,L CALL HEXPT ;PRINT 4 DIGIT HEX ADDR L25EB CALL CRLF ;CRLF AFTER ENTRY CALL CONTC ;CHECK FOR ABORT JZ WHAT ;ABORT THE DIRECTORY LIST POP B ;GET BACK ENTRIES/BLK & ENTRY LEN JMP L2595 ;TO SET UP FOR NEXT ENTRY ;********************************************************** ;**** THIS ROUTINE FINDS NEXT FILE TO BE "MOVED UP". **** ;**** 28F2 HAS 1ST "FREE" DISK ADDR (4 TO START WITH) **** ;**** COMPARE EACH FILE'S START ADDR TO IT; IF START **** ;**** ADR IS LOWER, FILE IS ALREADY COMPR. IF EQUAL, **** ;**** FILE IS COMPR, BUT NEED TO RETURN TO FIND NEW **** ;**** "1ST FREE" ADDR; IF GREATER, COMPARE FILE'S **** ;**** START ADDR WITH PREVIOUSLY SAVED LOWEST START **** ;**** ADDRESS OF FILE NEEDING COMPR & SAVE LOWER OF **** ;**** TWO, SETTING FLAG AT 28F1 SO MAIN ROUTINE KNOWS **** ;**** THAT A COMPRESSION RUN IS NEEDED AFTER ENTIRE **** ;**** DIRECTORY IS PROCESSED. CHK EVERY FILE ON DISK.**** ;********************************************************** L25F8 CPI ' ' ;IS ENTRY BLANK ? JZ L2595 ;YES--GO TO NEXT ENTRY LXI D,8 ;PUT NAME LENGTH IN D,E DAD D ;POINT TO START DISK ADDR XCHG ;MOVE POINTER TO START D.A. TO DE LHLD L28F2 ;GET END ADDR OF LAST COMPR FILE XCHG ;MOVE IT TO D,E POINTER TO H,L CALL COMPR ;CUR FILE BEG AT END OF LAST FILE? JZ L256D ;YES-RETN & UPDATE 1ST AVAIL BLOCK JNC L2595 ;NO-CUR FILE IS COMPR-GO TO NEXT XCHG ;CUR FILE NEEDS COMPR-PTR TO D,E LHLD L28F4 ;GET CUR LOWEST FILE NEEDING COMPR XCHG ;SET UP FOR TEST CALL COMPR ;COMPARE START ADDR OF TWO FILES JC L2595 ;ALREADY HAVE FILE W/LOWER ADDR CALL LDDEM ;THIS ONE LOWER--START ADDR TO D,E XCHG ;TO H,L SHLD L28F4 ;MAKE IT THE NEW "LOWEST" DISK ADR XRA A ;CLEAR ACC & FLAGS STA L28F1 ;0 TELLS CALLER WE NEED A COMPRSN JMP L2595 ;CHECK OUT NEXT FILE IN DIR BLOCK ;********************************************************** ;**** THIS IS THE KEYBOARD LINE INPUT ROUTINE. **** ;********************************************************** GETLN LXI H,LNBUF+2 ;ADDR OF 1ST CHAR AFTER COMMAND SHLD CLPTR ;STORE IT DCX H ;BACK UP TO BEG OF BUFFER DCX H LXI D,2001H ;E=CHAR COUNT+1; D=MAX NO OF CHAR L2633 XRA A CALL CIN ;GET CHAR MOV B,A CALL PRINT ;ECHO IT CPI '@' ;LINE DELETE CHAR ? JZ CRLFR ;YES--CRLF & RESTART CPI 5FH ;NO-CHAR DELETE CHAR ? JNZ L264E ;NO-PROCESS NORMAL CHAR INR D ;YES-INR NO OF ADDL CHAR ALLOWED DCR E ;DCR CHAR COUNT JZ CRLFR ;CRLF & RESET IF CHAR COUNT = 0 DCX H ;DCR INPUT LINE BUFFER POINTER JMP L2633 ;GET NEXT CHAR L264E MOV M,A ;PUT CHAR IN BUFFER CPI 0DH ;CARR RETURN ? MVI B,0AH ;SET UP LINE FEED JZ PRINT ;PRINT IF CR (CR WAS ECHOED) INX H ;NOT CR--INR BUFFER POINTER INR E ;INR CHAR COUNT DCR D ;DCR REMAINING BUFFER AVAIL JNZ L2633 ;NEXT CHAR IF BUFFER NOT FULL JMP WHAT ;DUMMY--BUFFER ONLY HOLDS 32 CHAR ;********************************************************** ;**** HEX TO BINARY CONVERSION. BINARY LEFT IN H,L. **** ;********************************************************** HXBIN CALL FTCHR ;GET 1ST HEX DIGIT CPI ' ' ;SPACE ? JZ HXBIN ;YES, TRY AGAIN LXI H,0 CNVRT CALL VLDTE ;CHAR BETWEEN 0-F ? JC WHAT ;NO--PRINT ERR MSG. DAD H ;YES--SHIFT H LEFT 1 BIT DAD H ;AGAIN DAD H ;AGAIN DAD H ;AGAIN ADD L ;PUT NEW CHAR + L IN A MOV L,A ;PUT RESULT BACK IN L CALL FTCHR ;GET NEXT HEX DIGIT RZ ;DONE IF CAR RET. CPI ' ' ;COULD BE SPACE JNZ CNVRT ;ITS NOT--PROCESS IT. RET ;IT IS--DONE. VLDTE CPI '0' ;LESS THAN 0 ? RC ;YES--RETURN CARRY SET CPI '9'+1 ;GREATER THAN 9 ? JNC CKHEX ;YES--CK FOR HEX DIGIT. SUI '0' ;NO--CONVERT TO BINARY. RET CKHEX CPI 'A' ;LESS THAN A ? RC ;YES--RETURN CARRY SET CPI 'F'+1 ;GREATER THAN F ? CMC RC ;YES--RETURN CARRY SET. SUI 37H ;SUBTRACT ASCII HEX BIAS. RET ;********************************************************** ;**** DECIMAL TO BINARY CONVERSION. BINARY IN H,L. **** ;********************************************************** DCBIN CALL FTCHR ;GET 1ST DEC DIGIT STC RZ ;AT LEAST 1 DIGIT REQD. CPI ' ' ;BUT SPACES ALLOWED JZ DCBIN LXI H,0 NXTDG CPI '9'+1 ;GREATER THAN 9 ? JNC WHAT ;YES--ERROR SUI '0' ;SUBTRACT 0 JC WHAT ;ERROR IF ANS NEG. MOV D,H MOV E,L ;ORIG NO TO D,E DAD H ; 2*H=2H DAD H ; 2*2H=4H DAD D ; 4H+H=5H DAD H ; 2*5H=10H MOV E,A MVI D,0 ;PUT NEW DIGIT IN D,E DAD D ;ADD IT TO H,L CALL FTCHR ;GET NEXT CHAR RZ ;CR, ' ' AND ',' TERMINATE STRING CPI ' ' RZ CPI ',' RZ JMP NXTDG ;********************************************************** ;**** THESE ARE NUMBER CONVERSION & PRINT ROUTINES **** ;********************************************************** HEXPT LXI D,-4096 ;SET UP FOR MSD OF 4 DIGIT HEX MVI C,'0' ;SUPRESS LEADING 0'S CALL PTDGT ;CALL PRINT DIGIT LXI D,-256 ;SET UP FOR 2ND MSB OF 4 HEX CALL PTDGT LXI D,-16 ;SET UP FOR 3RD MSB OF 4 HEX JMP NXTOL THDDP LXI D,-100 ;THREE DIGIT DECIMAL PRINT MVI C,'0' ;SUPRESS LEADING 0'S CALL PTDGT TDDPT LXI D,-10 ;SET UP FOR DECIMAL 10'S DIGIT NXTOL CALL PTDGT ;GET NEXT TO LSB, DEC OR HEX LXI D,-1 ;SET UP FOR UNITS DIGIT MVI C,0FFH ;TO KEEP FROM PRINTING SPACE PTDGT MVI B,'0'-1 ;INITIALIZE ASCII DIGIT GT0 SHLD LNBUF ;STORE POSITIVE REMAINDER INR B ;INR COUNT OF SUBTRACTIONS DAD D ;SUBTRACT AGAIN (D < 0) JC GT0 ;SUBTRACT AGAIN IF STILL > 0 LHLD LNBUF ;GET LAST POSITIVE REMAINDER MOV A,B ;CK FOR SUPRESSION OF LEADING 0'S CMP C ;SUPPRESS (YES IF C=30H) ? JZ PSPAC ;YES--PRINT SPACE INSTEAD OF 0 MVI C,0FFH ;DON'T SUPRESS ANY MORE 0'S CPI '9'+1 ;GREATER THAN 9 (EG, HEX A-F)? JC PRINT ;NO--PRINT AS IS ADI 7 ;YES--CONVERT TO ASCII HEX MOV B,A JMP PRINT ;PRINT IT ;********************************************************** ;**** FIVE UTILITY ROUTINES; PRINT SPACE, PRINT CHAR, **** ;**** CAR RET/LINE FEED & LOAD M FROM DE AND DE FROM M **** ;********************************************************** PSPAC MVI B,' ' PRINT XRA A JMP COUT CRLF MVI B,0DH CALL PRINT MVI B,0AH JMP PRINT LDMDE MOV M,E INX H MOV M,D INX H RET LDDEM MOV E,M INX H MOV D,M INX H RET ;********************************************************** ;**** GET THE DESIRED DRIVE FROM COMAND LINE & CONVERT **** ;**** IT TO BINARY. STORE DESIRED DRIVE AT 28EEH. **** ;********************************************************** GTDRV MVI C,1 ;1 IS DEFAULT IF NO DATA FOUND CALL FTCHR ;FETCH A CHARACTER JZ CRFND ;IF CARRIAGE RET FOUND CPI ' ' JZ GTDRV ;IF SPACE KEEP LOOKING SUI '0' ;CONVERT ASCII TO BINARY JZ WHAT ;ZERO INVALID MOV C,A ANI 0FCH JNZ WHAT ;ANS > 3 INVALID CRFND MOV A,C STA L28EE RET ;WITH ANSWER IN C,A AND AT 28EEH ;********************************************************** ;**** ROUTINE TO SUPPLY ONE CHAR FROM INPUT BUFFER **** ;********************************************************** FTCHR PUSH H LHLD CLPTR MOV A,M CPI 0DH JZ L274E INX H SHLD CLPTR L274E POP H RET L2750 CALL FTCHR ;ENTR HERE IF EOF REQD JNZ WHAT RET ;********************************************************** ;**** COMPARE D,E WITH STRING POINTED TO BY H,L **** ;********************************************************** COMPR INX H MOV A,D CMP M DCX H RNZ MOV A,E CMP M RET ;********************************************************** ;**** ROUTINES TO COMPARE DISK TO RAM MEMORY. VERY **** ;**** SIMILAR TO ROUTINES IN PROM BS AT E94C & E9AE. **** ;********************************************************** L275F MVI B,8CH ;MAX DELAY SECTR TO SYNC CHAR LXI D,BOARD+350H ;SET UP MEM MAP DATA READ ADDR MVI C,0 SWAIT LDA LEB10 ;LOAD A STAT REG INTO ACC ANI 4 ;MASK SYNC CHAR FOUND JNZ RDVER ;TO DO ACTUAL READ/VERIFY DCR B ;NOT FOUND-DCR COUNT JNZ SWAIT ;JUMP SYNC WAIT MVI A,1 ;TOO MUCH TIME PASSED JMP LE9AB ;ERROR ROUTINE IN PROM RDVER MOV B,C ;C & B HAVE 0 NXBYT LDAX D ;THIS IS ACTUAL READ STMNT CMP M ;COMPARE WITH RAM MVI A,3 JNZ LE9AB ;JUMP TO ERR IN PROM IF NOT SAME INX H ;OK--INR RAM ADDR DCR C ;DCR BYTES TO GO (DOING 256) JNZ NXBYT ;IF NOT DONE, CONTINUE POP PSW ;NO OF 256 BYTE BLOCKS TO CHECK DCR A RZ ;IF ZERO, DONE. PUSH PSW ;NOT DONE, PUT IT BACK CALL LE9CE ;WAIT FOR NEXT SECTOR HOLE JMP L275F ;AND DO NEXT BLOCK ;********************************************************** ;**** DISK WRITE ROUTINE. **** ;********************************************************** L278E LDA LEB04 ;START WRITE SECTOR SEQ L2791 LDA LEB10 ;LOAD A STATUS REG ANI 8 ;MASK WRITE STATUS BIT JZ L2791 ;WAIT IF NOT FOUND MVI D,BRD+2 ;THE "WRITE" ADDR-DATA OFFSET LXI B,000FH ;B = 0, C = 15 MOV E,B ;DATA TO WRITE IS ZERO L279F LDAX D ;WRITE A ZERO DCR C ;WRITE 15 OF THEM JNZ L279F ;IF NOT DONE MVI E,0FBH ;SET UP THE SYNC CHAR LDAX D ;WRITE IT L27A7 MOV A,M ;GET THE DATA TO WRITE MOV E,A ;SET IT UP XRA B ;WORKING ON CRC RLC ;STILL WORKING ON CRC MOV B,A ;SAVE PARTIAL CRC LDAX D ;WRITE THE DATA INX H ;POINT TO NEXT DATA BYTE DCR C ;DCR COUNT OF BYTES LEFT JNZ L27A7 ;TO DO NEXT BYTE MOV E,B ;SET TO WRITE CRC BYTE LDAX D ;DO IT POP PSW ;GET NO SECTORS LEFT TO DO DCR A ;DECREMENT BY ONE RZ ;RETURN IF ZERO PUSH PSW ;SAVE NO SECTORS CALL LE9CE ;WAIT FOR SECTOR HOLE JMP L200A ;TO DO NEXT SECTOR L27BE NOP L27BF NOP LNBUF DS 32 ;THESE ARE ACTUALLY NOP'S AREA DS 24 ;THESE ARE ACTUALLY DB 20H'S DS 232 ;THESE ARE ACTUALLY NOP'S L28E0 NOP NOP L28E2 NOP NOP L28E4 DS 2 ;THESE ARE ACTUALLY NOP'S L28E6 DS 8 ;A NAME BUFFER (ACT NOP'S) L28EE NOP L28EF NOP L28F0 NOP L28F1 NOP L28F2 NOP NOP L28F4 NOP NOP CLPTR DS 2 ;COMND LINE POINTER (ACT NOP) DS 8 ;ACTUALLY NOP'S L2900 DS 256 ;USER I/O AREA--ACTUALLY NOP'S