home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / BEEHIVE / OS / P2DOSV3.ARC / P2DOS.MAC < prev    next >
Text File  |  1991-08-11  |  78KB  |  2,531 lines

  1.     TITLE    'P2 DISK OPERATING SYSTEM'
  2. ;
  3. ;******************************************************************************
  4. ;*                                          *
  5. ;*  P 2 D O S --Z80 REPLACEMENT DISK OPERATING SYSTEM VERSION 2.1          *
  6. ;*                                          *
  7. ;*  COPYRIGHT (C) 1985 BY H.A.J. TEN BRUGGE                      *
  8. ;*  ALL RIGHTS RESERVED                                  *
  9. ;*                                          *
  10. ;*  P2DOS WAS WRITTEN BY H.A.J. TEN BRUGGE, WHO ASSUMES NO RESPONSIBILITY     *
  11. ;*  OR LIABILITY FOR ITS USE. P2DOS IS RELEASED TO THE PUBLIC DOMAIN FOR      *
  12. ;*  NON-COMMERCIAL USE ONLY.                              *
  13. ;*                                          *
  14. ;*  THE PULBLIC IS ENCOURAGED TO FREELY COPY AND USE THIS PROGRAM FOR         *
  15. ;*  NON-COMMERCIAL PURPOSES. ANY COMMERCIAL USE OF P2DOS IS PROHIBITED        *
  16. ;*  UNLESS APPROVED BY THE AUTHOR, H.A.J. TEN BRUGGE, IN WRITING.          *
  17. ;*  MY ADDRESS IS :                                  *    
  18. ;*   H.A.J. TEN BRUGGE,                                  *
  19. ;*   MOLENSTRAAT 33,                                  *
  20. ;*   7491 BD DELDEN                                  *
  21. ;*   PHONE NUMBER : 05407-61980                              *
  22. ;*                                          *
  23. ;*  THIS IS MOD 2.1 TO THE RELEASE VERSION OF P2DOS                  *
  24. ;*                                          *
  25. ;******************************************************************************
  26. ;
  27. RAMLOW    EQU    00000H            ; START ADDRESS MEMORY
  28. ;
  29. P2DOS    EQU    $            ; START ADDRESS P2DOS
  30. P2BIOS    EQU    P2DOS+00E00H        ; START ADDRESS P2BIOS
  31. ;
  32.     PAGE    44            ; 44 LINES/PAGE
  33. ;
  34. ;  P 2 D O S --Z80 REPLACEMENT DISK OPERATING SYSTEM VERSION 2.1
  35. ;
  36. ;
  37. ;
  38. ; NEW FEATURES OF P2DOS ARE:
  39. ;  - TEST CONSOLE STATUS AFTER 256 CHARACTERS OUTPUT. THIS MAKES IT POSSIBLE TO
  40. ;    EXIT A PROGRAM, AFTER YOU HIT ACCIDENTALY A KEY, BY TYPING ^S FOLLOWED BY ^C.  
  41. ;  - ERROR ROUTINES GIVE MORE INFORMATION.
  42. ;      P2DOS ERROR ON D: BAD SECTOR
  43. ;             SELECT
  44. ;             FILE R/O
  45. ;             R/O
  46. ;      FUNCTION =XXX (FILE =FILENAME.TYP)
  47. ;    AS YOU CAN SEE THE ERROR IS DISPLAYED WITH THE P2DOS FUNCTION CALL.
  48. ;    THE OPTION 'FILE =FILENAME.TYP' IS ONLY DISPLAYED IF THE P2DOS FUNCTION
  49. ;    USES A FILENAME. AFTER ALL ERRORS A WARM BOOT IS DONE.
  50. ;  - PUBLIC FILES ARE SUPPORTED. YOU CAN ACCESS A PUBLIC FILE FROM ANY USER NUMBER.
  51. ;    THIS MAKES IT POSSIBLE TO PUT FOR EXAMPLE ALL '.COM' IN A SPECIAL USER NUMBER
  52. ;    AND MAKE ALL THOSE FILES PUBLIC. YOU CAN ACCESS ALL THE FILES FROM ANY USER
  53. ;    USER NUMBER ON THE SAME DISK. 
  54. ;    A PUBLIC FILE IS A FILE WITH BIT F2 (BIT 7 FROM FILENAME LETTER 2) SET TO ONE.
  55. ;    PUBLIC FILES CAN ONLY BE REFERENCED BY THERE EXACT NAME AND NOT BY WILD CARD
  56. ;    CHARACTERS. 
  57. ;  - SEARCH PATH IS IMPLEMENTED JUST AS IN ZCPR2 TO FIND FILES ON OTHER DRIVES AND
  58. ;    IN OTHER USER AREAS. THE FILES MUST BE SYSTEM FILES AND MUST BE REFERENCED
  59. ;    BY THERE EXACT NAME AS IN PUBLIC FILE NAMES ABOVE.
  60. ;  - AUTOMATIC DATE AND TIME STAMP IS IMPLEMENTED. THE CREATION DATE AND TIME IS
  61. ;    SET WHEN THE FUNCTION MAKE IS EXECUTED. THE UPDATE DATE AND TIME IS SET AS
  62. ;    THE FILE IS CLOSED. TO LET THIS FEATURE WORK YOU NEED TO HAVE A REAL TIME
  63. ;    CLOCK AND THE CORRECT P2BIOS DRIVER ROUTINE. YOU ALSO HAVE TO INITIALISE YOUR
  64. ;    DIRECTORY FOR TIME STAMPS.   
  65. ;  - FILE R/O ERROR MESSAGE OCCURS IF ONE OF THE FOLLOWING FILE TYPES IS ACTIVE:
  66. ;     PUBLIC FILE (F2) AND YOU ARE NOT IN THE SAME USER AREA AS THE PUBLIC FILE IS
  67. ;     FILE R/O    (T1)
  68. ;     SYSTEM FILE (T2) AND YOU DID USE A QUESTION MARK
  69. ;    THIS MEANS THAT A SYSTEM FILE OR PUBLIC FILE CANNOT BE ERASED ACCIDENTALY.
  70. ;  - NEW FUNCTION GET TIME (200) IS IMPLEMENTED TO GET THE CORRECT DATE AND TIME.
  71. ;    ENTRY DE IS ADDRESS TO PUT TIME. THE DATE AND TIME RECORD HAS THE FOLLOWING
  72. ;    LAYOUT:
  73. ;    DATE:    DEFS    2    DATE = 1     (SU 01-JAN-1978)
  74. ;                DATE = 65535 (SU 05-JUN-2157)     
  75. ;    HOUR:    DEFS    1    HOUR IN BCD
  76. ;    MINUTE:    DEFS    1    MINUTE IN BCD
  77. ;    SECOND:    DEFS    1    SECOND IN BCD
  78. ;    FUNCTION WORKS ONLY IF CORRECT P2BIOS FUNCTION CALL IS INSTALLED.
  79. ;  - NEW FUNCTION SET TIME (201) IS IMPLEMENTED TO SET THE CORRECT DATE AND TIME.
  80. ;    ENTRY DE IS ADDRESS NEW TIME. THE DATE AND TIME LAYOUT IS AS ABOVE.
  81. ;    FUNCTION WORKS ONLY IF CORRECT P2BIOS FUNCTION CALL IS INSTALLED.
  82. ;  - ARCHIEVE BIT HAS BEEN IMPLEMENTED. THIS BIT MUST BE SET BY THE USER (OR
  83. ;    AN ARCHIEVE PROGRAM). THE BIT IS RESET WHEN THE FILE IS MODIFIED.
  84. ;  - DISK SIZE CAN BE AS LARGE AS 65536*16K=1 048 576 K BYTE=1 G BYTE. 
  85. ;  - FILE SIZE CAN BE AS LARGE AS 32*64*16K=32 768K BYTE=32 M BYTE.  
  86. ;
  87. ;
  88. ; YOU CAN ENABLE/DISABLE THE FUNCTIONS MENTIONED ABOVE WITH THE FOLLOWING DATA AND
  89. ; ADDRESSES.
  90. ;  - ENABLE PATH NAME BY PUTTING ADDRESS OF PATH IN P2DOS+11H. IF THIS VALUE IS 0000H
  91. ;    NO PATH IS USED. THIS ADDRESS IS NORMALLY SET TO 0040H.
  92. ;  - ENABLE P2DOS TIME AND DATE STAMPING BY PUTTING THE CORRECT P2BIOS ADDRESS AT
  93. ;    P2DOS+13H. THIS ADDRESS IS NORMALY SET TO THE P2BIOS CONSOLE STATUS FUNCTION. 
  94. ;  - YOU CAN ENABLE THE 256 CHARACTER DELAY FUNCTION BY SETTING BIT 0 OF ADDRESS
  95. ;    P2DOS+15H. THIS BIT IS NORMALLY SET TO 1.
  96. ;  - YOU CAN ENABLE PUBLIC FILES BY SETTING BIT 1 OF ADDRESS P2DOS+15H TO 1. THIS
  97. ;    BIT IS NORMALLY SET TO 1.
  98. ;
  99. ;
  100. ;
  101. ; ENTRY ADDRESSES P2BIOS
  102. ;
  103. ; FUNC    NAME    INPUT PARAMETERS    RETURNED VALUES
  104. ;  0    BOOT    NONE            NONE
  105. ;  1    WBOOT    NONE            NONE
  106. ;  2    CONST    NONE            A=0FFH IF READY
  107. ;                    A=000H IF NOT READY
  108. ;  3    CONIN    NONE            A=CONSOLE CHARACTER
  109. ;  4    CONOUT    C=CONSOLE CHARACTER    NONE
  110. ;  5    LIST    C=LIST CHARACTER    NONE
  111. ;  6    PUNCH    C=PUNCH CHARACTER    NONE
  112. ;  7    READER    NONE            A=READER CHARACTER
  113. ;  8    HOME    NONE            NONE
  114. ;  9    SELDSK    C=DRIVE NUMBER (0..15)    HL=DISK PARAMETER HEADER ADDRESS
  115. ;        E=INIT SELECT FLAG    HL=0000H IF INVALID DRIVE
  116. ; 10    SETTRK    BC=TRACK NUMBER        NONE
  117. ; 11    SETSEC    BC=SECTOR NUMBER    NONE
  118. ; 12    SETDMA    BC=DMA ADDRESS        NONE
  119. ; 13    READ    NONE            A=00H IF NO ERROR
  120. ;                    A=01H IF ERROR
  121. ; 14    WRITE    C=0 WRITE DATA        A=00H IF NO ERROR
  122. ;        C=1 WRITE DIRECTORY    A=01H IF ERROR
  123. ;        C=2 WRITE NEW DATA
  124. ; 15    LISTST    NONE            A=000H IF READY
  125. ;                    A=0FFH IF NOT READY
  126. ; 16    SECTRN    BC=LOGICAL SECTOR    HL=PHYSICAL SECTOR NUMBER
  127. ;            NUMBER
  128. ;        DE=TRANSLATION TABEL
  129. ;            ADDRESS
  130. ; XX    TIME    C=000H GET TIME        HL=POINTER TO TIME TABLE
  131. ;        C=0FFH UPDATE CLOCK        HL+0:DATE LSB SINCE 1,1,1978
  132. ;        HL=POINTER TO TIME        HL+1:DATE MSB
  133. ;            TABLE            HL+2:HOURS  (BCD)
  134. ;                        HL+3:MINUTES (BCD)
  135. ;                        HL+4:SECONDS (BCD)
  136. ;
  137. BOOT    EQU    P2BIOS+00000H        ; P2 SYSTEM COLD BOOT
  138. WBOOT    EQU    P2BIOS+00003H        ; P2 SYSTEM WARM BOOT
  139. CONST    EQU    P2BIOS+00006H        ; P2 SYSTEM CONSOLE STATUS
  140. CONIN    EQU    P2BIOS+00009H        ; P2 SYSTEM CONSOLE INPUT
  141. CONOUT    EQU    P2BIOS+0000CH        ; P2 SYSTEM CONSOLE OUTPUT
  142. LIST    EQU    P2BIOS+0000FH        ; P2 SYSTEM LIST OUTPUT
  143. PUNCH    EQU    P2BIOS+00012H        ; P2 SYSTEM PUNCH OUTPUT
  144. READER    EQU    P2BIOS+00015H        ; P2 SYSTEM READER INPUT
  145. HOME    EQU    P2BIOS+00018H        ; P2 SYSTEM HOME DISK
  146. SELDSK    EQU    P2BIOS+0001BH        ; P2 SYSTEM SELECT DISK
  147. SETTRK    EQU    P2BIOS+0001EH        ; P2 SYSTEM SELECT TRACK
  148. SETSEC    EQU    P2BIOS+00021H        ; P2 SYSTEM SELECT SECTOR
  149. SETDMA    EQU    P2BIOS+00024H        ; P2 SYSTEM SET DMA ADDRESS
  150. READ    EQU    P2BIOS+00027H        ; P2 SYSTEM READ 128 BYTES
  151. WRITE    EQU    P2BIOS+0002AH        ; P2 SYSTEM WRITE 128 BYTES
  152. LISTST    EQU    P2BIOS+0002DH        ; P2 SYSTEM LIST STATUS
  153. SECTRN    EQU    P2BIOS+00030H        ; P2 SYSTEM SECTOR TRANSLATION
  154. TIME    EQU    P2BIOS+00006H        ; P2 SYSTEM GET/SET TIME
  155.                     ; MUST BE CHANGED IF ROUTINE PRESENT
  156. ;
  157. ; INTERNAL DEFINITIONS
  158. ;
  159. CONTC    EQU    003H            ; KEY TO GENERATE WARM BOOT
  160. CONTE    EQU    005H            ; BREAK LINE
  161. CONTH    EQU    008H            ; BACKSPACE
  162. TAB    EQU    009H            ; TAB
  163. LF    EQU    00AH            ; LINE FEED
  164. CR    EQU    00DH            ; CARRIAGE RETURN
  165. CONTP    EQU    010H            ; SET/RESET PRINT FLAG
  166. CONTR    EQU    012H            ; REPEAT LINE
  167. CONTS    EQU    013H            ; STOP CONSOLE OUTPUT
  168. CONTU    EQU    015H            ; DELETE LINE
  169. CONTX    EQU    018H            ; DELETE LINE (BACKSPACES)
  170. DRVSEP    EQU    03AH            ; DRIVE SEPERATOR (:)
  171. RUBOUT    EQU    07FH            ; DELETE LAST CHAR
  172. ;
  173. MAXCMD    EQU    40            ; NUMBER OF VALID P2DOS COMMANDS
  174. ;
  175. ; START PROGRAM
  176. ;
  177. VERS:    DEFB    000H            ; VERSION NUMBER NOT IMPLEMENTED
  178.     DEFB    000H
  179.     DEFB    000H
  180.     DEFB    000H
  181.     DEFB    000H
  182.     DEFB    000H
  183. ;
  184. ; START P2DOS
  185. ;
  186. START:    JP    ENTRY            ; JUMP TO ENTRY POINT P2DOS
  187. ;
  188. ; ERROR MESSAGES P2DOS
  189. ;
  190. STBDSC:    DEFW    BADSEC            ; BAD SECTOR MESSAGE
  191. STSEL:    DEFW    SELERR            ; SELECT ERROR
  192. STRO:    DEFW    RDONLY            ; DRIVE READ ONLY
  193. SFILRO:    DEFW    FILRO            ; FILE READ ONLY
  194. ;
  195. ; EXTERNAL PATH NAME
  196. ;
  197. PATH:    DEFW    RAMLOW+00040H        ; PATHNAME FOR OPEN FILE COMMAND
  198. ;
  199. ; TIME ADDRESS P2BIOS
  200. ;
  201. TIMEAD:    DEFW    TIME            ; TIME ROUTINE ADDRESS FOR TIME
  202.                     ; AND DATE STAMPS
  203. ;
  204. ; FLAGS FOR SPECIALS
  205. ; BIT 0: PUBLIC FILE ENABLE(1)/DISABLE(0)
  206. ; BIT 1: DELAY 256 CHARACTERS ACTIVE(1)/DISABLE(0)
  207. ;
  208. FLAGS:    DEFB    0FFH            ; FLAG BITE
  209. ;
  210. ; ENTRY POINT P2DOS COMMANDS
  211. ;
  212. ENTRY:    LD    A,C            ; GET FUNCTION NUMBER
  213.     LD    (FUNCT),A        ; SAVE IT FOR LATER USE
  214.     LD    HL,0            ; SET HL TO ZERO
  215.     LD    (PEXIT),HL        ; CLEAR EXIT CODE
  216.     XOR    A            ; CLEAR A
  217.     LD    (FLDRV),A        ; RESET DRIVE SELECT DONE FLAG
  218.     LD    (RDWR),A        ; RESET READ/WRITE FLAG
  219.     LD    (SPSAVE),SP        ; SAVE STACK POINTER
  220.     LD    SP,P2DOSS        ; GET INTERNAL STACK POINTER
  221.     PUSH    IX            ; SAVE INDEX REGISTER
  222.     PUSH    DE            ; SAVE PARAMETER REGISTER
  223.     POP    IX            ; GET IT BACK IN IX
  224.     LD    HL,P2EXIT        ; GET EXIT ADDRESS P2DOS
  225.     PUSH    HL            ; SAVE IT ON STACK TO RETURN FROM P2DOS
  226.     LD    A,C            ; GET FUNCTION CODE
  227.     CP    200            ; TEST GET TIME
  228.     JP    Z,GETTIM        ; YES THEN GET TIME
  229.     CP    201            ; TEST SET TIME
  230.     JP    Z,SETTIM        ; YES THEN SET TIME
  231.     CP    MAXCMD+1        ; TEST GREATER THEN MAXCMD 
  232.     RET    NC            ; IF SO RETURN TO CALLER AND DO NOTHING
  233.     LD    HL,CTABLE        ; LOAD TABLE
  234.     LD    B,0            ; PREPARE 16 BIT ADD
  235.     ADD    HL,BC            ; ADD
  236.     ADD    HL,BC            ; ADD TWICE TO GET WORD VALUE
  237.     LD    A,(HL)            ; GET LSB
  238.     INC    HL            ; POINTER TO MSB
  239.     LD    H,(HL)            ; GET MSB
  240.     LD    L,A            ; SAVE LSB IN L 
  241.     JP    (HL)            ; JUMP TO ROUTINE
  242. ;
  243. ; COMMAND TABLE
  244. ;
  245. ;
  246. ; FUNC    NAME            INPUT PARAMETERS    RETURNED VALUES
  247. ;   0    BOOT            NONE            NONE
  248. ;   1    CONSOLE INPUT        NONE            A=CHARACTER
  249. ;   2    CONSOLE OUTPUT        E=CHARACTER        A=00H
  250. ;   3    READER INPUT        NONE            A=CHARACTER
  251. ;   4    PUNCH OUTPUT        E=CHARACTER        A=00H
  252. ;   5    LIST OUTPUT        E=CHARACTER        A=00H
  253. ;   6    DIRECT CONSOLE I/O    E=0FFH            A=INPUT CHARACTER
  254. ;                            A=00H IF NO CHARACTER PRESENT
  255. ;                E=0FEH            A=CONSOLE STATUS
  256. ;                E=000H..0FDH        A=00H
  257. ;   7    GET I/O BYTE        NONE            A=I/O BYTE (RAMLOW+03H)
  258. ;   8    SET I/O BYTE        E=I/O BYTE        A=00H
  259. ;   9    PRINT STRING        DE=ADDRESS STRING    A=00H
  260. ;  10    READ CONSOLE BUFFER    DE=ADDRESS BUFFER    A=00H
  261. ;  11    GET CONSOLE STATUS    NONE            A=00H IF NO CHARACTER PRESENT
  262. ;                            A=01H IF CHARACTER PRESENT
  263. ;  12    RETURN VERSION NUMBER    NONE            A=VERSION NUMBER (022H)
  264. ;  13    RESET DISK SYSTEM    NONE            A=00H NO $*.* FILE
  265. ;                            A=FFH $*.* FILE PRESENT
  266. ;  14    SELECT DISK        E=DISK NUMBER        A=00H
  267. ;  15    OPEN FILE        DE=ADDRESS FCB        A=DIRECTORY CODE
  268. ;  16    CLOSE FILE        DE=ADDRESS FCB        A=DIRECTORY CODE
  269. ;  17    SEARCH FOR FIRST    DE=ADDRESS FCB        A=DIRECTORY CODE
  270. ;  18    SEARCH FOR NEXT        DE=ADDRESS FCB        A=DIRECTORY CODE
  271. ;  19    DELETE FILE        DE=ADDRESS FCB        A=ERROR CODE
  272. ;  20    READ SEQUENTIAL        DE=ADDRESS FCB        A=READ/WRITE CODE
  273. ;  21    WRITE SEQUENTIAL    DE=ADDRESS FCB        A=READ/WRITE CODE
  274. ;  22    MAKE FILE        DE=ADDRESS FCB        A=DIRECTORY CODE
  275. ;  23    RENAME FILE        DE=ADDRESS FCB        A=ERROR CODE
  276. ;  24    RETURN LOGIN VECTOR    NONE            HL=LOGIN VECTOR
  277. ;  25    RETURN CURRENT DISK    NONE            A=CURRENT DISK
  278. ;  26    SET DMA ADDRESS        DE=DMA ADDRESS        A=00H
  279. ;  27    GET ALLOCATION ADDRESS    NONE            HL=ADDRESS ALLOCATION VECTOR
  280. ;  28    WRITE PROTECT DISK    NONE            A=00H
  281. ;  29    GET R/O VECTOR        NONE            HL=R/O VECTOR
  282. ;  30    SET FILE ATTRIBUTES    DE=ADDRESS FCB        A=ERROR CODE
  283. ;  31    GET ADDRESS DPB        NONE            HL=ADDRESS DPB
  284. ;  32    SET/GET USER CODE    E=0FFH            A=USER NUMBER
  285. ;                E=USER NUMBER        A=00H
  286. ;  33    READ RANDOM        DE=ADDRESS FCB        A=READ/WRITE CODE
  287. ;  34    WRITE RANDOM        DE=ADDRESS FCB        A=READ/WRITE CODE
  288. ;  35    COMPUTE FILE SIZE    DE=ADDRESS FCB        A=ERROR CODE
  289. ;  36    SET RANDOM RECORD    DE=ADDRESS FCB        A=00H
  290. ;  37    RESET MULTIPLE DRIVE    DE=MASK            A=00H
  291. ;  38    NOT IMPLEMENTED        NONE            A=00H
  292. ;  39    NOT IMPLEMENTED        NONE            A=00H
  293. ;  40    WRITE RANDOM WITH    DE=ADDRESS FCB        A=READ/WRITE CODE
  294. ;     ZERO FILL
  295. ; 200    GET TIME        DE=ADDRESS TO PUT TIME    A=00H
  296. ; 201    SET TIME        DE=ADDRESS TIME        A=00H
  297. ;
  298. ; DIRECTORY CODE : A=00H,01H,02H,03H IF NO ERROR
  299. ;                  A=0FFH IF ERROR
  300. ; ERROR CODE     : A=00H IF NO ERROR
  301. ;                  A=0FFH IF ERROR
  302. ; READ/WRITE CODE: A=00H IF NO ERROR
  303. ;           A=01H READ  => END OF FILE
  304. ;             WRITE => DIRECTORY FULL
  305. ;           A=02H DISK FULL
  306. ;           A=03H CLOSE ERROR DURING RANDOM RECORD READ/WRITE
  307. ;           A=04H READ EMPTY RECORD DURING RANDOM RECORD READ
  308. ;           A=05H DIRECTORY FULL ERROR DURING RANDOM RECORD WRITE
  309. ;           A=06H RANDOM RECORD TOO LARGE DURING RANDOM RECORD READ/WRITE
  310. ;
  311. CTABLE:    DEFW    WBOOT            ; WARM BOOT 
  312.     DEFW    RDCON            ; CONSOLE INPUT
  313.     DEFW    BWRCON            ; CONSOLE OUTPUT
  314.     DEFW    RDRDR            ; READER INPUT
  315.     DEFW    WPUNCH            ; PUNCH OUTPUT
  316.     DEFW    WLIST            ; LIST OUTPUT
  317.     DEFW    DCIO            ; DIRECT CONSOLE I/O
  318.     DEFW    GIOST            ; GET I/O BYTE
  319.     DEFW    SIOST            ; SET I/O BYTE
  320.     DEFW    MESS            ; PRINT STRING
  321.     DEFW    RDBUF            ; READ CONSOLE BUFFER
  322.     DEFW    TSTCS            ; GET CONSOLE STATUS
  323.     DEFW    CMND12            ; RETURN VERSION NUMBER
  324.     DEFW    CMND13            ; RESET DISK SYSTEM
  325.     DEFW    CMND14            ; SELECT DISK
  326.     DEFW    CMND15            ; OPEN FILE
  327.     DEFW    CMND16            ; CLOSE FILE
  328.     DEFW    CMND17            ; SEARCH FOR FIRST
  329.     DEFW    CMND18            ; SEARCH FOR NEXT
  330.     DEFW    CMND19            ; DELETE FILE
  331.     DEFW    CMND20            ; READ SEQUENTIAL
  332.     DEFW    CMND21            ; WRITE SEQUENTIAL
  333.     DEFW    CMND22            ; MAKE FILE
  334.     DEFW    CMND23            ; RENAME FILE
  335.     DEFW    CMND24            ; RETURN LOGIN VECTOR
  336.     DEFW    CMND25            ; RETURN CURRENT DISK
  337.     DEFW    CMND26            ; SET DMA ADDRESS
  338.     DEFW    CMND27            ; GET ADDRESS ALLOCATION VECTOR
  339.     DEFW    CMND28            ; WRITE PROTECT DISK
  340.     DEFW    CMND29            ; GET R/O VECTOR
  341.     DEFW    CMND30            ; SET FILE ATTRIBUTES
  342.     DEFW    CMND31            ; GET ADDRESS DISK PARAMETER HEADER(DPH) 
  343.     DEFW    CMND32            ; GET/SET USER CODE
  344.     DEFW    CMND33            ; READ RANDOM
  345.     DEFW    CMND34            ; WRITE RANDOM
  346.     DEFW    CMND35            ; COMPUTE FILE SIZE
  347.     DEFW    CMND36            ; SET RANDOM RECORD
  348.     DEFW    CMND37            ; RESET MULTIPLE DRIVE
  349.     DEFW    DUMMY            ; NOT IMPLEMENTED 
  350.     DEFW    DUMMY            ; NOT IMPLEMENTED 
  351.     DEFW    CMND40            ; WRITE RANDOM WITH ZERO FILL
  352. ;
  353. ; I/O ROUTINES
  354. ;
  355. ; P2DOS CONSOLE INPUT
  356. ;
  357. ; READ CHARACTER FROM CONSOLE AND ECHO
  358. ;  IF CHAR=CR,LF,TAB,CONTH OR >=SPACE
  359. ;
  360. RDCON:    CALL    GETCH            ; GET CHARACTER
  361.     CALL    TSTCH            ; TEST IF CR,LF,TAB,CONTH OR >=SPACE
  362.     JR    C,EXIT            ; NO THEN EXIT
  363.     CALL    WRCON            ; ECHO CHARACTER
  364. EXIT:    LD    (PEXIT),A        ; RETURN CHARACTER 
  365. DUMMY:    RET                ; AND EXIT P2DOS
  366. ;
  367. ; P2DOS WRITE CONSOLE
  368. ;
  369. BWRCON:    LD    A,E            ; COPY CHARAKTER
  370.     JR    WRCON            ; AND OUTPUT IT
  371. ;
  372. ; READ READER
  373. ;
  374. RDRDR:    CALL    READER            ; GET CHARACTER FROM READER
  375.     JR    EXIT            ; AND RETURN IT TO CALLER 
  376. ;
  377. ; WRITE PUNCH
  378. ;
  379. WPUNCH:    LD    C,E            ; COPY CHARACTER
  380.     JP    PUNCH            ; AND OUTPUT IT TO PUNCH DEVICE
  381. ;
  382. ; WRITE LIST
  383. ;
  384. WLIST:    LD    C,E            ; COPY CHARACTER
  385.     JP    LIST            ; AND OUTPUT IT TO LIST DEVICE
  386. ;
  387. ; DIRECT CONSOLE INPUT/OUTPUT
  388. ;
  389. DCIO:    LD    C,E            ; COPY CHARACTER
  390.     INC    E            ; TEST IF 0FFH
  391.     JR    Z,DCIO0            ; YES DO INPUT
  392.     INC    E            ; TEST IF 0FEH
  393.     JP    NZ,CONOUT        ; NO THEN OUTPUT CHARACTER
  394.     CALL    CONST            ; GET CONSOLE STATUS
  395.     AND    1            ; TEST IT
  396.     JR    EXIT            ; AND RETURN IT TO CALLER
  397. DCIO0:    CALL    CONST            ; GET CONSOLE STATUS
  398.     AND    1            ; TEST IT
  399.     RET    Z            ; EXIT IF NO CHARACTER PRESENT
  400.     CALL    CONIN            ; GET CHARACTER
  401.     JR    EXIT            ; AND RETURN IT TO CALLER
  402. ;
  403. ; GET I/O STATUS BYTE
  404. ;
  405. GIOST:    LD    A,(RAMLOW+00003H)    ; GET I/O BYTE FROM RAM
  406.     JR    EXIT            ; AND RETURN IT TO CALLER
  407. ;
  408. ; SET I/O STATUS BYTE
  409. ;
  410. SIOST:    LD    A,E            ; COPY I/O BYTE
  411.     LD    (RAMLOW+00003H),A    ; AND SAVE IT IN RAM
  412.     RET                ; EXIT TO CALLER
  413. ;
  414. ; TEST CONSOLE STATUS
  415. ;
  416. TSTCS:    CALL    GCONST            ; GET CONSOLE STATUS
  417.     JR    EXIT            ; AND RETURN IT TO CALLER
  418. ;
  419. ; OUTPUT CHAR (CONTROL CHAR = ^CHAR)
  420. ;
  421. OUTCH:    CALL    TSTCH            ; TEST IT CR,LF,TAB,CONTH OR >=SPACE
  422.     JR    NC,WRCON        ; YES THEN JUMP
  423.     PUSH    AF            ; SAVE CHARACTER
  424.     LD    A,'^'            ; LOAD A WITH '^' 
  425.     CALL    WRCON            ; OUTPUT IT
  426.     POP    AF            ; GET CHARACTER BACK
  427.     PUSH    AF            ; SAVE IT AGAIN
  428.     ADD    A,'A'-1            ; ADD OFFSET
  429.     CALL    WRCON            ; OUTPUT IT
  430.     POP    AF            ; GET CHARACTER
  431.     RET                ; RETURN TO CALLER
  432. ;
  433. ; ECHO CR,LF
  434. ;
  435. CROUT:    LD    A,CR            ; A=CARRIAGE RETURN
  436.     CALL    WRCON            ; OUTPUT IT
  437.     LD    A,LF            ; A=LINE FEED
  438.                     ; FALL THROUGH TO OUTPUT ROUTINE
  439. ;
  440. ; WRITE CHARACTER ON CONSOLE
  441. ;
  442. WRCON:    CP    TAB            ; TEST IF TAB
  443.     JR    NZ,WRCON1        ; NO THEN JUMP
  444. WRCON0:    LD    A,' '            ; EXPAND TAB WITH SPACES
  445.     CALL    WRCON            ; WRITE SPACE
  446.     LD    A,(TABCNT)        ; GET TAB COUNT
  447.     AND    7            ; TEST IF DONE
  448.     JR    NZ,WRCON0        ; NO THEN REPEAT
  449.     LD    A,TAB            ; RETURN TAB
  450.     RET                ; RETURN TO CALLER
  451. WRCON1:    PUSH    AF            ; SAVE CHARACTER
  452.     CALL    GCONST            ; TEST STATUS AND CONTS/CONTC
  453.     POP    AF            ; GET CHARACTER BACK
  454.     PUSH    AF            ; SAVE IT AGAIN
  455.     LD    C,A            ; COPY IT
  456.     CALL    CONOUT            ; OUTPUT IT
  457.     POP    AF            ; GET CHARACTER BACK
  458.     PUSH    AF            ; SAVE IT AGAIN
  459.     LD    C,A            ; COPY IT
  460.     LD    A,(FCONTP)        ; GET PRINTER ECHO FLAG 
  461.     OR    A            ; TEST IT
  462.     CALL    NZ,LIST            ; NON ZERO => OUTPUT CHAR TO PRINTER
  463.     LD    A,(FLAGS)        ; GET FLAG BYTE
  464.     BIT    1,A            ; TEST DELAY 256 BYTES ACTIVE
  465.     JR    Z,WRCON2        ; NO THEN EXIT
  466.     LD    HL,DELAY        ; GET DELAY COUNTER
  467.     XOR    A            ; A=0 
  468.     OR    (HL)            ; TEST COUNTER=0
  469.     JR    Z,WRCON2        ; YES THEN EXIT
  470.     DEC    (HL)            ; ELSE DECREMENT COUNTER
  471. WRCON2:    POP    AF            ; RESTORE CHARACTER
  472.                     ; FALL THROUGH TO COUNT ROUTINE
  473. ;
  474. ; COUNT CHARAKTERS IN LINE
  475. ;
  476. COUNTC:    LD    HL,TABCNT        ; GET POINTER TO TAB COUNTER
  477.     CP    RUBOUT            ; TEST IF CHARACTER = RUBOUT
  478.     RET    Z            ; YES NO UPDATE TAB COUNTER
  479.     INC    (HL)            ; INCREMENT TAB COUNTER
  480.     CP    ' '            ; TEST IF CHAR >= ' '
  481.     RET    NC            ; YES, NORMAL CHARACTER THEN EXIT
  482.     DEC    (HL)            ; CONTROL CHARACTER, DECREMENT TAB COUNT
  483.     CP    CONTH            ; TEST BACKSPACE
  484.     JR    NZ,COUNT0        ; NO BACKSPACE THEN JUMP
  485.     DEC    (HL)            ; DECREMENT TAB COUNTER
  486.     RET                ; AND EXIT
  487. COUNT0:    CP    CR            ; TEST CARRIAGE RETURN
  488.     JR    NZ,COUNT1        ; NO THEN JUMP
  489.     LD    (HL),0            ; RESET TAB COUNT
  490.     RET                ; AND EXIT
  491. COUNT1:    CP    TAB            ; TEST TAB CHARACTER
  492.     RET    NZ            ; NO THEN EXIT
  493.     PUSH    AF            ; SAVE CHARACTER
  494.     LD    A,(HL)            ; GET TAB COUNT
  495.     ADD    A,8            ; ADVANCE IT 8 POSITION
  496.     AND    0F8H            ; SET IT TO NEXT TAB POSITION
  497.     LD    (HL),A            ; SAVE IT
  498.     POP    AF            ; RESTORE CHARACTER 
  499.     RET                ; AND EXIT
  500. ;
  501. ; GET CHARAKTER FROM CONSOLE
  502. ;
  503. GETCH:    LD    HL,LASTCH        ; GET POINTER TO LAST INPUT CHARACTER
  504.     LD    A,(HL)            ; GET CHARACTER
  505.     LD    (HL),0            ; RESET LAST CHARACTER
  506.     OR    A            ; TEST IF CHARACTER PRESENT
  507.     RET    NZ            ; RETURN IF SO
  508.     JP    CONIN            ; ELSE GET CHARACTER
  509. ;
  510. ; GET CONSOLE STATUS
  511. ;
  512. GCONST:    LD    A,(DELAY)        ; GET 256 BYTES DELAY
  513.     OR    A            ; TEST IT
  514.     JR    NZ,GCONS0        ; NON ZERO, DELAY STIL ACTIVE OR DISABLED
  515.     CALL    CONST            ; GET CONSOLE STATUS
  516.     AND    1            ; TEST IT
  517.     JR    NZ,GCONS1        ; NON ZERO THEN GET CHARACTER
  518. GCONS0:    LD    A,(LASTCH)        ; GET LAST CHARACTER
  519.     OR    A            ; TEST IT
  520.     JR    NZ,GCONS3        ; NON ZERO THEN CHARACTER PRESENT
  521.     CALL    CONST            ; GET CONSOLE STATUS
  522.     AND    1            ; TEST IT
  523.     RET    Z            ; RETURN IF NO CHARACTER PRESENT
  524. GCONS1:    CALL    CONIN            ; GET CHARACTER
  525.     CP    CONTS            ; TEST STOP CHARACTER
  526.     JR    NZ,GCONS2        ; NOT THEN EXIT CHARACTER
  527.     CALL    CONIN            ; GET NEXT CHARACTER
  528.     CP    CONTC            ; TEST IF USER WANTS TO EXIT
  529.     JP    Z,RAMLOW+00000H        ; YES THEN WARM BOOT
  530.     JR    GCONST            ; TEST AGAIN
  531. GCONS2:    LD    (LASTCH),A        ; SAVE CHARACTER
  532.     LD    A,0FFH            ; SET DELAY COUNTER
  533.     LD    (DELAY),A        ; AND SAVE IT
  534. GCONS3:    LD    A,1            ; CHARACTER PRESENT CODE
  535.     RET                ; RETURN TO CALLER
  536. ;
  537. ; TEST CHARACTER
  538. ;  EXIT CARRY=0: CR,LF,TAB,CONTH OR >=SPACE
  539. ;       CARRY=1: ALL OTHER CHARACTERS
  540. ;
  541. TSTCH:    CP    CR            ; TEST CARRIAGE RETURN
  542.     RET    Z            ; RETURN IF SO
  543.     CP    LF            ; TEST LINE FEED
  544.     RET    Z            ; RETURN IF SO
  545.     CP    TAB            ; TEST TAB
  546.     RET    Z            ; RETURN IF SO
  547.     CP    CONTH            ; TEST BACKSPACE
  548.     RET    Z            ; RETURN IF SO
  549.     CP    ' '            ; TEST >=SPACE
  550.     RET                ; RETURN TO CALLER
  551. ;
  552. ; WRITE BACKSPACE,SPACE,BACKSPACE
  553. ;
  554. WCONTH:    CALL    WCONT0            ; WRITE BACKSPACE
  555.     LD    C,' '            ; LOAD SPACE
  556.     CALL    CONOUT            ; AND OUTPUT IT
  557. WCONT0:    LD    C,CONTH            ; LOAD BACKSPACE
  558.     JP    CONOUT            ; AND OUTPUT IT
  559. ;
  560. ; OUTPUT MESSAGE
  561. ;
  562. MESS:    LD    A,(DE)            ; GET BYTE FROM BUFFER
  563.     CP    '$'            ; TEST LAST BYTE
  564.     RET    Z            ; YES, THEN RETURN TO CALLER
  565.     INC    DE            ; POINT TO NEXT BYTE
  566.     PUSH    DE            ; SAVE POINTER
  567.     CALL    WRCON            ; OUTPUT CHARACTER
  568.     POP    DE            ; RESTORE POINTER
  569.     JR    MESS            ; AND TEST AGAIN
  570. ;
  571. ; AGAIN PRINTS #,CR,LF AND ADVANCES TO TABCX1
  572. ;
  573. AGAIN:    LD    A,'#'            ; LOAD '#'
  574.     CALL    WRCON            ; OUTPUT IT
  575. AGAIN0:    CALL    CROUT            ; OUTPUT CARRIAGE RETURN/LINE FEED
  576. AGAIN1:    LD    HL,TABCNT        ; GET TAB COUNT POINTER
  577.     LD    A,(TABCX1)        ; GET POSITION FIRST CHARACTER LINE
  578.     CP    (HL)            ; CHECK IT
  579.     RET    Z            ; RETURN IF ON SAME POSITION
  580.     LD    A,' '            ; LOAD SPACE
  581.     CALL    WRCON            ; OUTPUT IT
  582.     JR    AGAIN1            ; AND TEST AGAIN
  583. ;
  584. ; DELETE CHAR
  585. ;  ENTRY : HL=START BUFFER-1
  586. ;          B =CHARACTER COUNTER (ALWAYS>0)
  587. ;
  588. DELCH:    DEC    B            ; DECREMENT CHARACTER COUNTER
  589.     LD    A,(TABCNT)        ; GET TAB COUNTER
  590.     PUSH    AF            ; SAVE IT
  591.     PUSH    BC            ; SAVE CHARACTER COUNTER
  592.     LD    A,(TABCX1)        ; GET POSITION FIRST CHARACTER LINE
  593.     LD    (TABCNT),A        ; SAVE IT IN TAB COUNTER
  594. DELCH0:    LD    A,B            ; COPY CHARACTER COUNTER
  595.     OR    A            ; TEST IF 0
  596.     JR    Z,DELCH2        ; YES THEN JUMP
  597.     DEC    B            ; DECREMENT IT
  598.     INC    HL            ; INCREMENT BUFFER POINTER
  599.     LD    A,(HL)            ; GET CHARACTER FROM BUFFER
  600.     PUSH    HL            ; SAVE BUFFER POINTER
  601.     CALL    TSTCH            ; TEST IF CR,LF,TAB,CONTH OR >=SP
  602.     JR    NC,DELCH1        ; YES THEN JUMP
  603.     RRA                ; ELSE MUST BE CONTROL CHARACTER
  604.     CALL    COUNTC            ; COUNT CONTROL CHARACTER TWICE
  605. DELCH1:    CALL    COUNTC            ; COUNT CHARACTER
  606.     POP    HL            ; GET BUFFER POINTER
  607.     JR    DELCH0            ; AND TEST AGAIN
  608. DELCH2:    POP    BC            ; RESTORE CHARACTER COUNTER
  609.     POP    AF            ; AND TAB COUNTER
  610.     PUSH    HL            ; SAVE BUFFER POINTER
  611.     PUSH    BC            ; AND CHARACTER COUNTER
  612.     LD    HL,TABCNT        ; GET TAB COUNTER POINTER
  613.     SUB    (HL)            ; CALCULATE DIFFERENCE
  614. DELCH3:    DEC    A            ; DECREMENT IT
  615.     CP    8            ; COMPARE WITH 8
  616.     JR    NC,DELCH4        ; JUMP IF >=8
  617.     PUSH    AF            ; SAVE DIFFERENCE
  618.     CALL    WCONTH            ; REMOVE CHARACTER END LINE
  619.     POP    AF            ; RESTORE COUNTER
  620.     JR    DELCH3            ; REMOVE MORE CHARACTERS
  621. DELCH4:    POP    BC            ; RESTORE CHARACTER COUNTER
  622.     POP    HL            ; RESTORE BUFFER POINTER
  623.     RET                ; AND RETURN TO CALLER 
  624. ;
  625. ; READ BUFFER
  626. ;
  627. RDBUF:    LD    A,(TABCNT)        ; GET CURRENT POSITION CURSOR
  628.     LD    (TABCX1),A        ; SAVE IT
  629. RDBUF0:    PUSH    IX            ; SAVE START ADDRESS BUFFER
  630.     POP    HL            ; GET IT IN HL
  631.     LD    C,(HL)            ; GET MAXIMUM LINE LENGHT
  632.     INC    HL            ; INCREMENT TO LINE LENGHT POSITION
  633.     LD    B,0            ; CLEAR LINE LENGHT COUNTER
  634.     PUSH    HL            ; SAVE START LINE - 1
  635. RDBUF1:    PUSH    HL            ; SAVE REGISTERS
  636.     PUSH    BC
  637. RDBUF2:    CALL    GETCH            ; GET CHARACTER
  638.     POP    BC            ; RESTORE REGISTERS
  639.     POP    HL
  640.     AND    07FH            ; MASK CHARACTER
  641.     CP    CONTE            ; TEST IF CONTE
  642.     JR    NZ,RDBUF3        ; NOT THEN JUMP 
  643.     PUSH    HL            ; SAVE REGISTERS
  644.     PUSH    BC
  645.     CALL    AGAIN0            ; MOVE CURSOR TO NEXT LINE
  646.     JR    RDBUF2            ; AND GET NEXT CHAR
  647. RDBUF3:    CP    CONTH            ; TEST BACKSPACE
  648.     JR    NZ,RDBUF4        ; NOT THEN JUMP
  649.     LD    A,B            ; TEST IF DELETING CHAR FROM EMPTY LINE
  650.     OR    A
  651.     JR    Z,RDBUF1        ; YES THEN GET NEXT CHAR
  652.     POP    HL            ; GET START LINE
  653.     PUSH    HL            ; AND SAVE IT AGAIN
  654.     CALL    DELCH            ; DELETE CHARACTER
  655.     JR    RDBUF1            ; GET NEXT CHARACTER
  656. RDBUF4:    CP    CONTP            ; TEST PRINT ENABLE/DISABLE
  657.     JR    NZ,RDBUF6        ; NOT THEN JUMP
  658.     LD    A,(FCONTP)        ; COMPLEMENT PRINT FLAG
  659.     CPL
  660.     LD    (FCONTP),A
  661. RDBUF5:    JR    RDBUF1            ; AND GET NEXT CHARACTER
  662. RDBUF6:    CP    CONTR            ; TEST REPEAT LINE
  663.     JR    NZ,RDBUFA        ; NOT THEN JUMP
  664.     PUSH    BC            ; SAVE REGISTERS
  665.     CALL    AGAIN            ; MOVE CURSOR TO NEXT LINE
  666.     POP    BC            ; RESTORE REGISTERS
  667.     POP    HL            ; GET START LINE
  668.     PUSH    HL            ; SAVE IT AGAIN
  669.     PUSH    BC            ; SAVE LINE COUNTER/MAXIMUM LINE LENGHT
  670. RDBUF7:    LD    A,B            ; TEST LAST CHARACTER ECHOED 
  671.     OR    A
  672.     JR    Z,RDBUF8        ; YES THEN JUMP
  673.     INC    HL            ; INCREMENT POINTER
  674.     LD    A,(HL)            ; GET CHARACTER
  675.     DEC    B            ; DECREMENT LINE COUNTER
  676.     PUSH    HL            ; SAVE REGISTERS
  677.     PUSH    BC
  678.     CALL    OUTCH            ; OUTPUT CHARACTER
  679.     POP    BC            ; RESTORE REGISTERS
  680.     POP    HL
  681.     JR    RDBUF7            ; AND TEST END LINE
  682. RDBUF8:    POP    BC            ; RESTORE LINE COUNTER/MAXIMUM LINE LENGHT
  683. RDBUF9:    JR    RDBUF5            ; AND GET NEXT CHAR
  684. RDBUFA:    CP    CONTU            ; TEST DELETE LINE
  685.     JR    NZ,RDBUFC        ; NOT THEN JUMP
  686.     POP    HL            ; GET START LINE
  687.     CALL    AGAIN            ; MOVE CURSOR TO NEXT LINE
  688. RDBUFB:    JR    RDBUF            ; AND START ROUTINE AGAIN
  689. RDBUFC:    CP    CONTX            ; TEST DELETE LINE
  690.     JR    NZ,RDBUFE        ; NOT THEN JUMP
  691. RDBUFD:    POP    HL            ; GET START LINE
  692.     LD    A,B            ; TEST IF LAST CHARACTER DELETED
  693.     OR    A
  694.     JR    Z,RDBUFB        ; YES START ROUTINE AGAIN
  695.     PUSH    HL            ; SAVE POINTER
  696.     CALL    DELCH            ; DELETE LAST CHARACTER LINE
  697.     JR    RDBUFD            ; TEST LAST CHARACTER DELETED
  698. RDBUFE:    CP    RUBOUT            ; TEST DELETE LAST CHARACTER
  699.     JR    NZ,RDBUFF        ; NOT THEN JUMP
  700.     LD    A,B            ; TEST FIRST CHARACTER LINE
  701.     OR    A
  702.     JR    Z,RDBUF9        ; YES, DO NOT DELETE
  703.     LD    A,(HL)            ; GET LAST CHARACTER
  704.     DEC    HL            ; DECREMENT POINTER LINE
  705.     DEC    B            ; DECREMENT LINE COUNTER
  706.     JR    RDBUFG            ; ECHO LAST CHARACTER
  707. RDBUFF:    CP    CR            ; TEST CARRIAGE RETURN
  708.     JR    Z,RDBUFI        ; YES, THEN EXIT
  709.     CP    LF            ; TEST LINE FEED
  710.     JR    Z,RDBUFI        ; YES THEN EXIT
  711.     INC    HL            ; INCREMENT POINTER
  712.     LD    (HL),A            ; AND SAVE CHARACTER
  713.     INC    B            ; INCREMENT LINE COUNTER
  714. RDBUFG:    PUSH    HL            ; SAVE REGISTERS
  715.     PUSH    BC
  716.     CALL    OUTCH            ; ECHO CHARACTER
  717.     POP    BC            ; RESTORE REGISTERS
  718.     POP    HL
  719.     CP    CONTC            ; TEST WARM BOOT
  720.     LD    A,B            ; GET LINE COUNT
  721.     JR    NZ,RDBUFH        ; NO WARM BOOT THEN JUMP
  722.     CP    1            ; TEST CONTC IS FIRST CHARACTER LINE 
  723.     JP    Z,RAMLOW+00000H        ; YES THEN EXECUTE WARM BOOT
  724. RDBUFH:    CP    C            ; TEST LINE LENGHT=MAXIMUM LINE LENGHT
  725.     JR    NZ,RDBUF9        ; NOT THEN GET NEXT CHARACTER
  726. RDBUFI:    POP    HL            ; GET START LINE - 1
  727.     LD    (HL),B            ; SAVE LINE COUNTER
  728.     LD    A,CR            ; LOAD CARRIAGE RETURN
  729.     JP    WRCON            ; AND ECHO IT
  730. ;
  731. ;******************************************************************************
  732. ;*                                          *
  733. ;*     DISK FUNCTIONS                                  *
  734. ;*                                          *
  735. ;******************************************************************************
  736. ;
  737. ; RETURN VERSION NUMBER
  738. ;
  739. CMND12:    LD    A,22H            ; SET VERSION NUMBER
  740.     JR    CMD25A            ; AND EXIT
  741. ;
  742. ; RESET DISK SYSTEM
  743. ;
  744. CMND13:    LD    HL,0            ; LOAD ZERO
  745.     LD    (LOGIN),HL        ; ALL DRIVES LOGED OUT
  746.     LD    (DSKRO),HL        ; ALL DRIVES READ/WRITE
  747.     LD    HL,RAMLOW+00080H    ; SET UP DMA ADDRESS
  748.     LD    (DMA),HL        ; AND SAVE IT
  749.     CALL    STDMA            ; DO P2BIOS CALL
  750.     XOR    A            ; SET DEFAULT DRIVE = 'A'
  751.     LD    (DEFDRV),A        ; SAVE IT
  752.     CALL    SELDK            ; SELECT DRIVE 'A'
  753.     LD    A,(SUBFLG)        ; GET SUBMIT FLAG
  754.     JR    CMD25A            ; EXIT
  755. ;
  756. ; SEARCH FOR FILE
  757. ;
  758. CMND17:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  759.     LD    A,(IX+0)        ; GET DRIVE NUMBER FROM FCB
  760.     SUB    '?'            ; TEST IF '?'
  761.     JR    Z,CMD17B        ; IF SO ALL ENTRIES MATCH
  762.     LD    A,(IX+14)        ; GET SYSTEM BYTE
  763.     CP    '?'            ; TEST IF '?' 
  764.     JR    Z,CMD17A        ; YES, JUMP
  765.     LD    (IX+14),0        ; LOAD SYSTEM BYTE WITH ZERO
  766. CMD17A:    LD    A,15            ; TEST FIRST 15 ITEMS IN FCB
  767. CMD17B:    CALL    SEARCH            ; DO SEARCH
  768. CMD17C:    LD    HL,(DIRBUF)        ; COPY DIRECTORY BUFFER 
  769.     LD    DE,(DMA)        ; TO DMA ADDRESS
  770.     LD    BC,128            ; DIRECTORY=128 BYTES 
  771.     LDIR
  772.     RET                ; EXIT
  773. ;
  774. ; SEARCH FOR NEXT OCCURENCE FILE
  775. ;
  776. CMND18:    LD    IX,(DCOPY)        ; GET LAST FCB USED BY SEARCH
  777.     CALL    SELDRV            ; SELEXT DRIVE FROM FCB
  778.     CALL    SEARCN            ; SEARCH NEXT FILE MATCH
  779.     JR    CMD17C            ; AND COPY DIRECTORY TO DMA ADDRESS
  780. ;
  781. ; DELETE FILE
  782. ;
  783. CMND19:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  784.     CALL    DELETE            ; DELETE FILE
  785. CMD19A:    LD    A,(SEAREX)        ; GET EXIT BYTE 00=FILE FOUND,0FFH NOT
  786.     JR    CMD25A            ; AND EXIT
  787. ;
  788. ; RENAME FILE
  789. ;
  790. CMND23:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  791.     CALL    RENAM            ; RENAME FILE
  792.     JR    CMD19A            ; AND EXIT
  793. ;
  794. ; RETURN LOGIN VECTOR
  795. ;
  796. CMND24:    LD    HL,(LOGIN)        ; GET LOGIN VECTOR
  797. CMD24A:    LD    (PEXIT),HL        ; SAVE IT
  798.     RET                ; AND EXIT
  799. ;
  800. ; RETURN CURRENT DRIVE
  801. ;
  802. CMND25:    LD    A,(DEFDRV)        ; GET CURRENT DRIVE
  803. CMD25A:    JP    EXIT            ; AND EXIT
  804. ;
  805. ; RETURN ALV VECTOR
  806. ;
  807. CMND27:    LD    HL,(ALV)        ; GET ALLOCATION VECTOR
  808.     JR    CMD24A            ; AND EXIT
  809. ;
  810. ; RETURN DISK R/O VECTOR
  811. ;
  812. CMND29:    LD    HL,(DSKRO)        ; GET DISK R/O VECTOR
  813.     JR    CMD24A            ; AND EXIT
  814. ;
  815. ; CHANGE STATUS
  816. ;
  817. CMND30:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  818.     CALL    CSTAT            ; CHANGE STATUS
  819.     JR    CMD19A            ; AND EXIT
  820. ;
  821. ; RETURN DRIVE TABEL
  822. ;
  823. CMND31:    LD    HL,(IXP)        ; GET DRIVE TABLE
  824.     JR    CMD24A            ; AND EXIT
  825. ;
  826. ; SET/GET USER CODE
  827. ;
  828. CMND32:    LD    A,E            ; GET USER CODE
  829.     INC    A            ; TEST IF 0FFH
  830.     LD    A,(USER)        ; GET OLD USER CODE
  831.     JR    Z,CMD25A        ; IF 0FFH THEN EXIT
  832.     LD    A,E            ; GET NEW USER CODE
  833.     AND    01FH            ; MASK IT
  834.     LD    (USER),A        ; SAVE IT
  835.     RET                ; AND EXIT
  836. ;
  837. ; COMPUTE FILE SIZE COMMAND
  838. ;
  839. CMND35:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  840.     CALL    FILSZ            ; COMPUTE FILE SIZE
  841.     JR    CMD19A            ; AND EXIT
  842. ;
  843. ; SET RANDOM RECORD COUNT
  844. ;
  845. CMND36:    LD    HL,32            ; SET POINTER TO NEXT RECORD
  846.     CALL    CALRRC            ; CALCULATE RANDOM RECORD COUNT
  847. LDRRC:    LD    (IX+33),D        ; AND SAVE RANDOM RECORD COUNT
  848.     LD    (IX+34),C
  849.     LD    (IX+35),B
  850.     RET                ; AND EXIT
  851. ;
  852. ; RESET MULTIPLE LOGIN DRIVE
  853. ;
  854. CMND37:    LD    A,E            ; GET MASK LSB
  855.     CPL                ; COMPLEMENT IT
  856.     LD    E,A 
  857.     LD    A,D            ; GET MASK MSB
  858.     CPL                ; COMPLEMENT IT
  859.     LD    D,A
  860.     LD    HL,(LOGIN)        ; GET LOGIN VECTOR
  861.     LD    A,E            ; MASK LOGIN VECTOR
  862.     AND    L            ; LSB
  863.     LD    L,A
  864.     LD    A,D            ; MASK LOGIN VECTOR
  865.     AND    H            ; MSB
  866.     LD    H,A
  867.     LD    (LOGIN),HL        ; SAVE LOGIN VECTOR
  868.     EX    DE,HL            ; USE LOGIN VECTOR AS MASK
  869.     LD    HL,(DSKRO)        ; GET DRIVE R/O VECTOR
  870.     LD    A,E            ; MASK DRIVE R/O VECTOR
  871.     AND    L            ; LSB
  872.     LD    L,A
  873.     LD    A,D            ; MASK DRIVE R/O VECTOR
  874.     AND    H            ; LSB
  875.     LD    H,A
  876.     LD    (DSKRO),HL        ; SAVE DRIVE R/O VECTOR
  877.     RET                ; AND EXIT
  878. ;
  879. ;******************************************************************************
  880. ;*                                          *
  881. ;*     ERROR ROUTINES                                  *
  882. ;*                                          *
  883. ;******************************************************************************
  884. ;
  885. ; BAD SECTOR ERROR
  886. ;
  887. BADSEC:    LD    DE,MBADSC        ; LOAD BAD SECTOR MESSAGE
  888.     JR    DERROR            ; AND DISPLAY ERROR
  889. ;
  890. ; SELECT ERROR
  891. ;
  892. SELERR:    LD    DE,MSEL            ; LOAD SELECT ERROR MESSAGE
  893.     JR    DERROR            ; AND DIPLAY ERROR
  894. ;
  895. ; FILE READ ONLY ERROR
  896. ;
  897. FILRO:    LD    DE,MFILRO        ; LOAD FILE R/O MESSAGE
  898.     LD    A,0FFH            ; SET FILE R/O MESSAGE FLAG
  899.     JR    ERROR            ; AND DISPLAY ERROR
  900. ;
  901. ; DRIVE READ ONLY ERROR
  902. ;
  903. RDONLY:    LD    DE,MRO            ; LOAD DRIVE R/O MESSAGE
  904. DERROR:    XOR    A            ; SET NO FILE R/O MESSAGE
  905. ;
  906. ; DISPLAY ERROR MESSAGE
  907. ;
  908. ; P2DOS ERROR ON D: ERROR MESSAGE
  909. ; FUNCTION = NN  [FILE = FILENAME.TYP]
  910. ;
  911. ERROR:    LD    C,A            ; SAVE FILE R/O MESSAGE FLAG
  912.     PUSH    BC
  913.     PUSH    DE            ; SAVE ERROR MESSAGE POINTER
  914.     CALL    CROUT            ; DISPLAY CR/LF
  915.     LD    A,(DEFDRV)        ; GET CURRENT DRIVE
  916.     ADD    A,'A'            ; MAKE ASCII
  917.     LD    (MDRIVE),A        ; SAVE IT
  918.     LD    DE,MBERR        ; LOAD MESSAGE "P2DOS ERROR ON D:"
  919.     CALL    MESS            ; DISPLAY MESSAGE
  920.     POP    DE            ; GET ERROR MESSAGE POINTER
  921.     CALL    MESS            ; DISPLAY MESSAGE
  922.     CALL    CROUT            ; DISPLAY CR/LF
  923.     LD    DE,MBFUNC        ; LOAD MESSAGE "FUNCTION ="
  924.     CALL    MESS            ; DISPLAY MESSAGE
  925.     LD    A,(FUNCT)        ; GET FUNCTION NUMBER
  926.     PUSH    AF            ; SAVE IT
  927.     LD    BC,100            ; DISPLAY NUMBER / 100
  928.     CALL    NUM
  929.     LD    C,10            ; DISPLAY NUMBER / 10
  930.     CALL    NUM
  931.     LD    BC,101H            ; ALWAYS DISPLAY NUMBER / 1
  932.     CALL    NUM
  933.     POP    AF            ; GET FUNCTION NUMBER
  934.     POP    BC            ; GET FILE R/O FLAG
  935.     CP    15            ; TEST IF FCB USED IN COMMAND
  936.     JR    C,ERROR3
  937.     CP    24
  938.     JR    C,ERROR1
  939.     CP    30
  940.     JR    Z,ERROR1
  941.     CP    33
  942.     JR    C,ERROR3
  943.     CP    37
  944.     JR    C,ERROR1
  945.     CP    40
  946.     JR    NZ,ERROR3
  947. ERROR1:    PUSH    IX            ; YES THEN DISPLAY "FILE ="
  948.     SUB    19            ; TEST DELETE FILE FUNCTION
  949.     JR    NZ,ERROR2        ; NOT THEN JUMP
  950.     OR    C            ; TEST FILE R/O FLAG
  951.     JR    Z,ERROR2        ; NO FILE R/O THEN JUMP
  952.     CALL    CALDIR            ; GET FCB FROM DIRECTORY BUFFER
  953.     EX    (SP),HL            ; SAVE IT
  954. ERROR2:    LD    DE,MFILE        ; GET MESSAGE " FILE ="
  955.     CALL    MESS            ; DISPLAY MESSAGE
  956.     POP    HL            ; GET POINTER FCB
  957.     LD    B,8            ; DISPLAY FIRST 8 CHARACTERS
  958.     CALL    FILENM
  959.     LD    A,'.'            ; LOAD '.'
  960.     PUSH    HL            ; SAVE FCB POINTER
  961.     CALL    WRCON            ; ECHO IT
  962.     POP    HL            ; RESTORE FCB POINTER
  963.     LD    B,3            ; DISPLAY LAST 3 CHARACTERS 
  964.     CALL    FILENM
  965. ERROR3:    CALL    GCONST            ; TEST IF CHARACTER PRESENT
  966.     OR    A
  967.     JR    Z,ERROR4        ; NO THEN JUMP
  968.     CALL    GETCH            ; GET CHARACTER
  969.     JR    ERROR3            ; AND TEST AGAIN
  970. ERROR4:    CALL    GETCH            ; GET CHARACTER
  971.     JP    RAMLOW+00000H        ; AND DO WARM BOOT
  972. ;
  973. ; DISPLAY NUMBER
  974. ;
  975. NUM:    LD    D,-1            ; LOAD NUMBER -1
  976. NUM1:    INC    D            ; INCREMENT NUMBER
  977.     SUB    C            ; DIVIDE BY C
  978.     JR    NC,NUM1            ; NOT FINISHED THEN LOOP
  979.     ADD    A,C            ; RESTORE LAST VALUE
  980.     PUSH    AF            ; SAVE IT
  981.     LD    A,D            ; TEST IF "0"
  982.     OR    B            ; AND IF LEADING ZERO
  983.     JR    Z,NUM2            ; YES, THEN EXIT 
  984.     LD    B,A            ; SET NO LEADING ZERO 
  985.     LD    A,D            ; GET NUMBER
  986.     ADD    A,'0'            ; MAKE ASCII
  987.     PUSH    BC            ; SAVE REGISTERS
  988.     CALL    WRCON            ; ECHO NUMBER
  989.     POP    BC            ; RESTORE REGISTERS
  990. NUM2:    POP    AF            ; RESTORE NUMBER
  991.     RET                ; AND EXIT
  992. ;
  993. ; DISPLAY FILNAME.TYP
  994. ;
  995. FILENM:    INC    HL            ; INCREMENT POINTER FCB
  996.     LD    A,(HL)            ; GET CHARACTER FROM FCB
  997.     AND    07FH            ; MASK IT
  998.     PUSH    HL            ; SAVE REGISTERS
  999.     PUSH    BC
  1000.     CALL    WRCON            ; ECHO CHARACTER
  1001.     POP    BC            ; RESTORE REGISTERS
  1002.     POP    HL
  1003.     DJNZ    FILENM            ; REPEAT B TIMES
  1004.     RET                ; AND EXIT
  1005. ;
  1006. ; ERROR MESSAGES
  1007. ;
  1008. MBADSC:    DEFM    'Bad sector$'
  1009. ;
  1010. MSEL:    DEFM    'Select$'
  1011. ;
  1012. MFILRO:    DEFM    'File '
  1013. ;
  1014. MRO:    DEFM    'R/O$'
  1015. ;
  1016. MBERR:    DEFM    'P2DOS error on '
  1017. MDRIVE:    DEFB    0
  1018.     DEFB    DRVSEP
  1019.     DEFM    ' $'
  1020. ;
  1021. MBFUNC:    DEFM    'Function =$'
  1022. ;
  1023. MFILE:    DEFM    ' File =$'
  1024. ;
  1025. ; SELECT DISK FROM FCB
  1026. ;
  1027. SELDRV:    LD    A,0FFH            ; SET DISK SELECT DONE FLAG
  1028.     LD    (FLDRV),A
  1029.     LD    A,(DEFDRV)        ; GET CURRENT DRIVE
  1030.     LD    (DRIVE),A        ; SAVE IT IN MEMORY
  1031.     LD    E,A            ; SAVE IT IN REGISTER E
  1032.     LD    A,(IX+0)        ; GET DRIVE FROM FCB
  1033.     LD    (FCB0),A        ; SAVE IT
  1034.     CP    '?'            ; TEST IF '?'
  1035.     JR    Z,CMND14        ; YES, THEN SELECT DRIVE FROM REGISTER E
  1036.     AND    01FH            ; MASK DRIVE
  1037.     LD    A,E            ; TEST IF ZERO
  1038.     JR    Z,SELDR0        ; SELECT DRIVE FROM REGISTER E
  1039.     LD    A,(IX+0)        ; GET DRIVE FROM FCB
  1040.     DEC    A            ; DECREMENT DRIVE
  1041. SELDR0:    CALL    SELDK            ; SELECT DRIVE
  1042.     LD    A,(IX+0)        ; GET DRIVE FROM FCB
  1043.     AND    0E0H            ; REMOVE DRIVE BITS
  1044.     LD    B,A            ; SAVE REGISTER
  1045.     LD    A,(USER)        ; GET USER NUMBER
  1046.     OR    B            ; INSERT USER NUMBER IN FCB
  1047.     LD    (IX+0),A
  1048.     RET                ; AND EXIT
  1049. ;
  1050. ; SELECT DISK
  1051. ;
  1052. CMND14:    LD    A,E            ; COPY DRIVE NUMBER
  1053. ;
  1054. ; SELECT DISK
  1055. ;
  1056. SELDK:    AND    0FH            ; MASK DRIVE NUMBER
  1057.     LD    B,A            ; SAVE COUNTER
  1058.     LD    DE,(LOGIN)        ; GET LOGIN VECTOR
  1059.     OR    A            ; TEST DRIVE 'A'
  1060.     JR    Z,SELDK1        ; YES THEN JUMP
  1061. SELDK0:    RR    D            ; SHIFT LOGIN VECTOR
  1062.     RR    E            ; UNTIL BIT 0 REGISTER E
  1063.     DJNZ    SELDK0            ; IS CURRENT DRIVE
  1064. SELDK1:    LD    HL,DEFDRV        ; GET POINTER LAST DRIVE
  1065.     BIT    0,E            ; TEST IF DRIVE LOGGED IN
  1066.     JR    Z,SELDK2        ; NO, LOGIN DRIVE
  1067.     CP    (HL)            ; TEST SAME DRIVE
  1068.     RET    Z            ; YES THEN EXIT
  1069. SELDK2:    LD    (HL),A            ; SAVE NEW CURRENT DRIVE
  1070.     PUSH    DE            ; SAVE DRIVE LOGGED IN FLAG
  1071.     LD    C,A            ; COPY DRIVE NUMBER
  1072.     CALL    SELDSK            ; DO P2BIOS SELECT 
  1073.     LD    A,H            ; TEST IF ERROR 
  1074.     OR    L
  1075.     JR    Z,SELDK3        ; YES, ILLEGAL DRIVE NUMBER
  1076.     LD    E,(HL)            ; GET LSB TRANSLATION VECTOR
  1077.     INC    HL            ; INCREMENT POINTER
  1078.     LD    D,(HL)            ; GET MSB TRANSLATION VECTOR
  1079.     INC    HL            ; INCREMENT POINTER
  1080.     LD    (TRANS),DE        ; SAVE TRANSLATION VECTOR
  1081.     LD    (TEMP0),HL        ; SAVE ADDRESS TEMP0
  1082.     INC    HL            ; INCREMENT TO NEXT ADDRESS
  1083.     INC    HL
  1084.     LD    (TEMP1),HL        ; SAVE ADDRESS TEMP1
  1085.     INC    HL            ; INCREMENT TO NEXT ADDRESS
  1086.     INC    HL
  1087.     LD    (TEMP2),HL        ; SAVE ADDRESS TEMP2
  1088.     INC    HL            ; INCREMENT TO NEXT ADDRESS
  1089.     INC    HL
  1090.     LD    DE,DIRBUF        ; LOAD DIRBUF POINTER
  1091.     LD    BC,8            ; COPY 8 BYTES
  1092.     LDIR
  1093.     LD    HL,(IXP)        ; GET DRIVE PARAMETER ADDRESS
  1094.     LD    C,15            ; COPY 15 BYTES
  1095.     LDIR
  1096.     POP    DE            ; GET DRIVE LOGGED IN FLAG
  1097.     BIT    0,E            ; TEST IT
  1098.     RET    NZ            ; DRIVE LOGGED IN SO RETURN
  1099.     LD    HL,(LOGIN)        ; GET LOGIN VECTOR
  1100.     CALL    SDRVB            ; SET DRIVE BIT IN LOGIN VECTOR
  1101.     LD    (LOGIN),HL        ; SAVE LOGIN VECTOR
  1102.     JR    INITDR            ; AND SETUP DRIVE TABLES
  1103. SELDK3:    LD    HL,(STSEL)        ; LOAD ERROR MESSAGE ADDRESS
  1104.     JP    (HL)            ; AND DISPLAY ERROR
  1105. ;
  1106. ; INIT DRIVE
  1107. ;  CLEAR ALV BIT BUFFER AFTER DRIVE RESET
  1108. ;
  1109. INITDR:    LD    DE,(MAXLEN)        ; GET LENGHT ALV BUFFER-1 (BITS)
  1110.     LD    A,3            ; DIVIDE BY 8
  1111. INITD0:    SRL    D            ; TO GET BYTES
  1112.     RR    E
  1113.     DEC    A
  1114.     JR    NZ,INITD0
  1115.     INC    DE            ; INCREMENT, SO ALL BITS ARE CLEARED
  1116.     LD    HL,(ALV)        ; GET POINTER ALV BUFFER
  1117.     PUSH    HL
  1118. INITD1:    LD    (HL),0            ; CLEAR 8 BITS
  1119.     INC    HL            ; INCREMENT POINTER
  1120.     DEC    DE            ; DECREMENT COUNTER
  1121.     LD    A,D            ; TEST IF COUNTER ZERO
  1122.     OR    E
  1123.     JR    NZ,INITD1        ; NOT THEN JUMP
  1124.     POP    HL            ; GET ALV POINTER
  1125.     LD    DE,(NDIR0)        ; GET FIRST TWO BYTES ALV BUFFER 
  1126.     LD    (HL),E            ; SAVE LSB
  1127.     INC    HL            ; INCREMENT POINTER
  1128.     LD    (HL),D            ; SAVE MSB
  1129.     LD    HL,(TEMP0)        ; CLEAR NUMBER OF FILES
  1130.     XOR    A            ; ON THIS DRIVE
  1131.     LD    (HL),A            ; CLEAR LSB
  1132.     INC    HL            ; INCREMENT POINTER
  1133.     LD    (HL),A            ; CLEAR MSB
  1134.     LD    (SUBFLG),A        ; CLEAR SUBMIT FLAG (RESET DISK COMMAND)
  1135.     CALL    SETFCT            ; SET FILE COUNT
  1136. INITD2:    LD    A,0FFH            ; UPDATE DIRECTORY CHECKSUM
  1137.     CALL    RDDIR            ; READ FCB'S FROM DIRECTORY
  1138.     CALL    TSTFCT            ; TEST LAST FCB
  1139.     RET    Z            ; YES THEN EXIT
  1140.     CALL    CALDIR            ; CALCULATE ENTRY POINT FCB
  1141.     LD    A,(HL)            ; GET FIRST BYTE FCB
  1142.     CP    0E5H            ; TEST EMPTY DIRECTORY ENTRY
  1143.     JR    Z,INITD2        ; YES THEN GET NEXT FCB
  1144.     CP    021H            ; TEST TIME STAMP
  1145.     JR    Z,INITD2        ; YES THEN GET NEXT FCB
  1146.     LD    A,(USER)        ; GET USER NUMBER
  1147.     CP    (HL)            ; TEST IF USER IS SAME
  1148.     JR    NZ,INITD3        ; NO THEN JUMP
  1149.     INC    HL            ; POINT TO FILE NAME
  1150.     LD    A,(HL)            ; GET FIRST CHAR FILENAME
  1151.     SUB    '$'            ; TEST IF '$'
  1152.     JR    NZ,INITD3        ; NOT THEN JUMP
  1153.     DEC    A            ; LOAD A WITH 0FFH
  1154.     LD    (SUBFLG),A        ; SAVE IT IN SUBFLG 
  1155. INITD3:    LD    C,1            ; SET BIT IN ALV BUFFER
  1156.     CALL    FILLBB            ; SET BITS FROM FCB IN ALV BUFFER
  1157.     CALL    SETLF            ; UPDATE LAST FILE COUNT
  1158.     JR    INITD2            ; AND GET NEXT FCB
  1159. ;
  1160. ; SET DRIVE BIT IN HL
  1161. ;
  1162. SDRVB:    EX    DE,HL            ; COPY HL=>DE 
  1163.     LD    HL,1            ; GET MASK DRIVE "A"
  1164.     LD    A,(DEFDRV)        ; GET CURRENT DRIVE
  1165.     OR    A            ; TEST IF DRIVE "A"
  1166.     JR    Z,SDRVB1        ; YES THEN DONE
  1167. SDRVB0:    ADD    HL,HL            ; GET NEXT MASK
  1168.     DEC    A            ; DECREMENT DRIVE COUNTER
  1169.     JR    NZ,SDRVB0        ; AND TEST IF DONE
  1170. SDRVB1:    LD    A,D            ; HL=HL OR DE
  1171.     OR    H
  1172.     LD    H,A
  1173.     LD    A,E
  1174.     OR    L
  1175.     LD    L,A
  1176.     RET                ; EXIT
  1177. ;
  1178. ; CALCULATE SECTOR/TRACK DIRECTORY
  1179. ;
  1180. STDIR:    LD    HL,(FILCNT)        ; GET FCB COUNTER DIRECTORY
  1181.     SRL    H            ; DIVIDE BY 4
  1182.     RR    L            ; (4 FCB'S / SECTOR)
  1183.     SRL    H
  1184.     RR    L
  1185.     LD    (RECDIR),HL        ; SAVE VALUE (USED BY CHECKSUM)
  1186.     EX    DE,HL            ; COPY IT TO DE
  1187.     LD    HL,0            ; CLEAR HL
  1188. ;
  1189. ; CALCULATE SECTOR/TRACK
  1190. ;  ENTRY: HL,DE=SECTOR NUMBER (128 BYTE SECTOR)
  1191. ;  RESULT SET TRACK  =HL,DE  /  MAXSEC
  1192. ;         SET SECTOR =HL,DE MOD MAXSEC
  1193. ;
  1194. CALST:    LD    BC,(MAXSEC)        ; GET SECTORS/TRACK
  1195.     LD    A,17            ; SET UP LOOP COUNTER
  1196. CALST0:    OR    A            ; TEST HL>=BC
  1197.     SBC    HL,BC
  1198.     CCF
  1199.     JR    C,CALST1        ; YES THEN JUMP
  1200.     ADD    HL,BC            ; NO THEN RESTORE HL
  1201.     OR    A            ; AND CLEAR CARRY
  1202. CALST1:    RL    E            ; SHIFT RESULT IN DE
  1203.     RL    D
  1204.     DEC    A            ; TEST LAST BIT DONE
  1205.     JR    Z,CALST2        ; YES THEN EXIT
  1206.     RL    L            ; SHIFT NEXT BIT IN HL
  1207.     RL    H
  1208.     JR    CALST0            ; CONTINUE
  1209. CALST2:    PUSH    HL            ; SAVE SECTOR NUMBER
  1210.     LD    HL,(NFTRK)        ; GET FIRST TRACK
  1211.     ADD    HL,DE            ; ADD TRACK NUMBER
  1212.     LD    B,H            ; COPY IT TO BC
  1213.     LD    C,L
  1214.     CALL    SETTRK            ; P2BIOS CALL SET TRACK
  1215.     POP    BC            ; RESTORE SECTOR NUMBER
  1216.     LD    DE,(TRANS)        ; GET TRANSLATION TABLE ADDRESS
  1217.     CALL    SECTRN            ; P2BIOS CALL SECTOR TRANSLATION 
  1218.     LD    B,H            ; COPY RESULT TO BC
  1219.     LD    C,L
  1220.     JP    SETSEC            ; P2BIOS CALL SET SECTOR
  1221. ;
  1222. ; GET DISK MAP BLOCK NUMBER FROM FCB
  1223. ;  EXIT HL=ADDRESS FCB
  1224. ;       DE=DM
  1225. ;       BC=OFFSET IN DM
  1226. ;
  1227. GETDM:    LD    C,(IX+32)        ; GET NEXT RECORD
  1228.     LD    A,(NBLOCK)        ; GET NUMBER OF BLOCKS
  1229.     LD    B,A            ; SAVE IT 
  1230. GETDM0:    SRL    C            ; SHIFT NEXT RECORD 
  1231.     DJNZ    GETDM0            ; NUMBER OF BLOCKS TIMES
  1232. GETDM1:    CPL                ; COMPLEMENT NUMBER OF BLOCKS
  1233.     ADD    A,9            ; ADD 9
  1234.     LD    B,A            ; B=8-NUMBER OF BLOCKS
  1235.     LD    A,(NEXTND)        ; GET EXTEND MASK
  1236.     AND    (IX+12)            ; MASK WITH EXTEND
  1237.     RRCA                ; ROTATE ONE RIGHT
  1238. GETDM2:    RLCA                ; ROTATE ONE LEFT
  1239.     DJNZ    GETDM2            ; 8-NUMBER OF BLOCKS TIMES
  1240. GETDM3:    ADD    A,C            ; ADD THE TWO VALUES TO GET ENTRY FCB
  1241. GETDM4:    PUSH    IX            ; GET FCB ADDRESS
  1242.     POP    HL
  1243.     LD    C,16            ; ADD OFFSET 16 TO POINT TO DM
  1244.     ADD    HL,BC
  1245.     LD    C,A            ; ADD ENTRY FCB
  1246.     ADD    HL,BC
  1247.     LD    A,(MAXLEN+1)        ; TEST 8 BITS/16 BITS FCB ENTRY
  1248.     OR    A
  1249.     JR    NZ,GETDM5        ; 16 BITS => JUMP
  1250.     LD    E,(HL)            ; GET 8 BIT VALUE
  1251.     LD    D,0            ; MAKE MSB ZERO
  1252.     RET                ; AND EXIT
  1253. GETDM5:    ADD    HL,BC            ; ADD TWICE (16 BIT VALUES)
  1254.     LD    E,(HL)            ; GET LSB
  1255.     INC    HL            ; INCREMENT POINTER
  1256.     LD    D,(HL)            ; GET MSB
  1257.     DEC    HL            ; DECREMENT POINTER
  1258.     RET                ; AND EXIT
  1259. ;
  1260. ; CALCULATE SECTOR NUMBER 
  1261. ;  ENTRY: DE=BLOCK NUMBER FROM FCB
  1262. ;
  1263. CALSEC:    LD    HL,0            ; CLEAR MSB SECTOR NUMBER
  1264.     LD    A,(NBLOCK)        ; GET LOOP COUNTER
  1265.     LD    B,A            ; SAVE IT IN B
  1266. CALSC0:    SLA    E            ; SHIFT L,D,E 
  1267.     RL    D
  1268.     RL    L
  1269.     DJNZ    CALSC0            ; B TIMES
  1270. CALSC1:    LD    A,(NMASK)        ; GET SECTOR MASK
  1271.     AND    (IX+32)            ; AND WITH NEXT RECORD
  1272.     OR    E            ; SET UP LSB SECTOR NUMBER
  1273.     LD    E,A
  1274.     RET                ; AND EXIT
  1275. ;
  1276. ; CALCULATE DIRBUF ENTRY POINT
  1277. ;
  1278. CALDIR:    LD    HL,(DIRBUF)        ; GET START ADDRESS DIRBUF
  1279.     LD    A,(SECPNT)        ; GET SECTOR POINTER
  1280.     ADD    A,L            ; ADD L=L+A
  1281.     LD    L,A
  1282.     RET    NC            ; NO CARRY EXIT
  1283.     INC    H            ; INCREMENT H
  1284.     RET                ; AND EXIT
  1285. ;
  1286. ; INIT FILE COUNT
  1287. ;
  1288. SETFCT:    LD    HL,-1            ; SET UP FILE COUNT
  1289.     LD    (FILCNT),HL        ; SAVE IT
  1290.     RET                ; AND EXIT
  1291. ;
  1292. ; TEST FILE COUNT
  1293. ;
  1294. TSTFCT:    LD    HL,(FILCNT)        ; TEST FILE COUNT=0FFFFH
  1295.     LD    A,H            ; GET MSB 
  1296.     AND    L            ; AND LSB
  1297.     INC    A            ; TEST IF RESULT=0FFH
  1298.     RET                ; AND EXIT
  1299. ;
  1300. ; SET LAST FILE
  1301. ;
  1302. SETLF:    CALL    TSTLF            ; TEST LAST FILE
  1303.     RET    C            ; NO THEN EXIT
  1304.     INC    DE            ; INCREMENT LAST FILE
  1305.     LD    (HL),D            ; SAVE IT IN TEMP0
  1306.     DEC    HL
  1307.     LD    (HL),E
  1308.     RET                ; AND EXIT
  1309. ;
  1310. ; TEST LAST FILE
  1311. ;
  1312. TSTLF:    LD    HL,(TEMP0)        ; GET POINTER TO LAST FILE 
  1313.     LD    DE,(FILCNT)        ; GET FILE COUNTER
  1314.     LD    A,E            ; SUBTRACT DE-(HL)
  1315.     SUB    (HL)
  1316.     INC    HL
  1317.     LD    A,D
  1318.     SBC    A,(HL)
  1319.     RET                ; EXIT
  1320. ;
  1321. ; GET NEXT FCB FROM DRIVE
  1322. ; ENTRY A=0 CHECK CHECKSUM, A=0FFH UPDATE CHECKSUM
  1323. ;
  1324. RDDIR:    LD    C,A            ; SAVE CHECKSUM FLAG
  1325.     LD    HL,(FILCNT)        ; GET FILE COUNTER
  1326.     INC    HL            ; INCREMENT IT
  1327.     LD    (FILCNT),HL        ; AND SAVE IT
  1328.     LD    DE,(NFILES)        ; GET MAXIMUM NUMBER OF FILES
  1329.     OR    A            ; CLEAR CARRY
  1330.     SBC    HL,DE            ; TEST IF LAST FILE
  1331.     ADD    HL,DE
  1332.     JR    Z,RDDIR0        ; NO JUMP
  1333.     JR    NC,SETFCT        ; YES SET FILE COUNT TO 0FFFFH
  1334. RDDIR0:    LD    A,L            ; GET FILE COUNT LSB
  1335.     ADD    A,A            ; *32 
  1336.     ADD    A,A
  1337.     ADD    A,A
  1338.     ADD    A,A
  1339.     ADD    A,A
  1340.     AND    060H            ; MASK IT
  1341.     LD    (SECPNT),A        ; SAVE IT FOR LATER USE
  1342.     RET    NZ            ; RETURN IF NOT FIRST FCB SECTOR
  1343.     PUSH    BC            ; SAVE CHECKSUM FLAG
  1344.     CALL    STDIR            ; CALCULATE SECTOR/TRACK DIRECTORY
  1345.     CALL    READDR            ; READ SECTOR DIRECTORY
  1346.     POP    BC            ; RESTORE CHECKSUM FLAG
  1347. ;
  1348. ; UPDATE/CHECK CHECKSUM DIRECTORY
  1349. ; ENTRY C=0 CHECK CHECKSUM, C=0FFH UPDATE CHECKSUM
  1350. ;
  1351. CHKDIR:    LD    HL,(NCHECK)        ; GET NUMBER OF CHECKED RECORDS
  1352.     LD    DE,(RECDIR)        ; GET CURRENT RECORD
  1353.     OR    A            ; CLEAR CARRY
  1354.     SBC    HL,DE            ; TEST CURRENT RECORD 
  1355.     RET    Z            ; EXIT IF ZERO
  1356.     RET    C            ; EXIT IF GREATER THEN NCHECK
  1357.     LD    HL,(DIRBUF)        ; GET DIRBUF
  1358.     LD    B,128            ; SET UP COUNTER
  1359.     XOR    A            ; CLEAR CHECKSUM
  1360. CHKDR0:    ADD    A,(HL)            ; ADD CHECKSUM
  1361.     INC    HL            ; INCREMENT POINTER
  1362.     DJNZ    CHKDR0            ; 128 TIMES
  1363.     LD    HL,(CSV)        ; GET POINTER CHECKSUM DIRECTORY
  1364.     ADD    HL,DE            ; ADD CURRENT RECORD
  1365.     INC    C            ; TEST CHECKSUM FLAG
  1366.     JR    Z,CHKDR1        ; 0FFH=> UPDATE CHECKSUM
  1367.     CP    (HL)            ; TEST CHECKSUM
  1368.     RET    Z            ; EXIT IF OK
  1369.     JP    SETWPD            ; SET WRITE PROTECT DISK
  1370. CHKDR1:    LD    (HL),A            ; UPDATE CHECKSUM
  1371.     RET                ; AND EXIT
  1372. ;
  1373. ; READ SECTOR FROM DRIVE
  1374. ;
  1375. READR:    CALL    READ            ; P2BIOS CALL READ SECTOR
  1376.     JR    WRITE0            ; TEST EXIT CODE
  1377. ;
  1378. ; WRITE SECTOR ON DRIVE
  1379. ;
  1380. WRITER:    CALL    WRITE            ; P2BIOS CALL WRITE SECTOR
  1381. WRITE0:    OR    A            ; TEST EXIT CODE
  1382.     RET    Z            ; EXIT IF OK
  1383.     LD    HL,(STBDSC)        ; LOAD BAD SECTOR MESSAGE POINTER
  1384.     JP    (HL)            ; P2DOS ERROR ON D: BAD SECTOR
  1385. ;
  1386. ; READ DIRECTORY FROM DRIVE
  1387. ;
  1388. READDR:    CALL    DMADIR            ; SET UP DMA DIRECTORY
  1389.     CALL    READR            ; READ RECORD
  1390.     JR    STDMA            ; SET UP DMA USER
  1391. ;
  1392. ; WRITE DIRECTORY ON DRIVE
  1393. ;
  1394. WRITDR:    LD    C,0FFH            ; UPDATE CHECKSUM DIRECTORY
  1395.     CALL    CHKDIR
  1396.     CALL    DMADIR            ; SET UP DMA DIRECTORY 
  1397.     LD    C,1            ; WRITE DIRECTORY FLAG
  1398.     CALL    WRITER            ; WRITE RECORD
  1399.     JR    STDMA            ; SET UP DMA USER
  1400. ;
  1401. ; SET DMA ADDRESS COMMAND
  1402. ;
  1403. CMND26:    LD    (DMA),DE        ; SAVE DMA ADDRESS
  1404. ;
  1405. ; SET DMA ADDRESS
  1406. ;
  1407. STDMA:    LD    BC,(DMA)        ; GET DMA ADDRESS
  1408.     JR    DMADR0            ; AND DO P2BIOS CALL
  1409. ;
  1410. ; SET DMA ADDRESS DIRECTORY
  1411. ;
  1412. DMADIR:    LD    BC,(DIRBUF)        ; GET DMA ADDRESS DIRECTORY
  1413. DMADR0:    JP    SETDMA            ; P2BIOS CALL SET DMA
  1414. ;
  1415. ; GET BIT FROM ALV BUFFER
  1416. ;  ENTRY DE=BLOCK NUMBER
  1417. ;  EXIT  A =BIT IN LSB
  1418. ;        B =BITNUMBER IN A
  1419. ;        HL=POINTER IN ALV BUFFER
  1420. ;
  1421. GETBIT:    LD    A,E            ; GET BIT NUMBER
  1422.     AND    7            ; MASK IT
  1423.     INC    A            ; ADD 1
  1424.     LD    B,A            ; SAVE IT
  1425.     LD    C,A            ; TWICE
  1426.     SRL    D            ; GET BYTE NUMBER
  1427.     RR    E            ; DE=DE/8
  1428.     SRL    D
  1429.     RR    E
  1430.     SRL    D
  1431.     RR    E
  1432.     LD    HL,(ALV)        ; GET START ADDRESS ALV BUFFER
  1433.     ADD    HL,DE            ; ADD BYTE NUMBER
  1434.     LD    A,(HL)            ; GET 8 BITS
  1435. GETBT0:    RLCA                ; GET CORRECT BIT
  1436.     DJNZ    GETBT0
  1437.     LD    B,C            ; RESTORE BIT NUMBER
  1438.     RET                ; AND RETURN TO CALLER
  1439. ;
  1440. ; SET/RESET BIT IN ALV BUFFER
  1441. ;  ENTRY DE=BLOCK NUMBER
  1442. ;        C =0 RESET BIT, C=1 SET BIT
  1443. ;
  1444. SETBIT:    PUSH    BC            ; SAVE SET/RESET BIT
  1445.     CALL    GETBIT            ; GET BIT
  1446.     AND    0FEH            ; MASK IT
  1447.     POP    DE            ; GET SET/RESET BIT
  1448.     OR    E            ; SET/RESET BIT
  1449. SETBT0:    RRCA                ; ROTATE BIT IN CORRECT POSITION
  1450.     DJNZ    SETBT0
  1451.     LD    (HL),A            ; SAVE 8 BITS
  1452.     RET                ; AND RETURN TO CALLER
  1453. ;
  1454. ; FILL BIT BUFFER FROM FCB IN DIRBUF
  1455. ;  ENTRY C=0 RESET BIT, C=1 SET BIT
  1456. ;
  1457. FILLBB:    CALL    CALDIR            ; GET DIRECTORY ENTRY
  1458.     LD    DE,16            ; GET OFFSET DM BLOCK
  1459.     ADD    HL,DE            ; ADD OFFSET
  1460.     LD    B,E            ; GET BLOCK COUNTER
  1461. FILLB0:    LD    E,(HL)            ; GET LSB BLOCK NUMBER
  1462.     INC    HL            ; INCREMENT POINTER
  1463.     LD    D,0            ; RESET MSB BLOCK NUMBER
  1464.     LD    A,(MAXLEN+1)        ; TEST >256 BLOCKS PRESENT
  1465.     OR    A
  1466.     JR    Z,FILLB1        ; NO THEN JUMP
  1467.     DEC    B            ; DECREMENT BLOCK COUNTER
  1468.     LD    D,(HL)            ; GET CORRECT MSB
  1469.     INC    HL            ; INCREMENT POINTER
  1470. FILLB1:    LD    A,D            ; TEST BLOCK NUMBER
  1471.     OR    E            
  1472.     JR    Z,FILLB2        ; ZERO THEN GET NEXT BLOCK
  1473.     PUSH    HL            ; SAVE POINTER
  1474.     PUSH    BC            ; SAVE COUNTER AND SET/RESET BIT
  1475.      LD    HL,(MAXLEN)        ; GET MAXIMUM LENGHT ALV BUFFER
  1476.     OR    A            ; RESET CARRY
  1477.     SBC    HL,DE            ; TEST DE<=MAXLEN ALV BUFFER 
  1478.     CALL    NC,SETBIT        ; YES THEN INSERT BIT
  1479.     POP    BC            ; GET COUNTER AND SET/RESET BIT
  1480.     POP    HL            ; GET POINTER
  1481. FILLB2:    DJNZ    FILLB0            ; REPEAT FOR ALL DM ENTRIES
  1482.     RET                ; AND RETURN TO CALLER
  1483. ;
  1484. ; SET WRITE PROTECT DISK COMMAND
  1485. ;
  1486. CMND28:
  1487. ;
  1488. ; SET WRITE PROTECT DISK
  1489. ;
  1490. SETWPD:    LD    HL,(DSKRO)        ; GET DISK R/O VECTOR
  1491.     CALL    SDRVB            ; INCLUDE DRIVE BIT
  1492.     LD    (DSKRO),HL        ; SAVE DISK R/O BIT
  1493.     LD    DE,(NFILES)        ; GET MAXIMUM NUMBER OF FILES-1 
  1494.     INC    DE            ; INCREMENT IT 
  1495.     LD    HL,(TEMP0)        ; GET POINTER TO DISK PARAMETER BLOCK 
  1496.     LD    (HL),E            ; AND SAVE NUMBER OF FILES
  1497.     INC    HL
  1498.     LD    (HL),D
  1499.     RET                ; AND RETURN TO CALLER
  1500. ;
  1501. ; CHECK FILE R/O BIT
  1502. ;
  1503. CHKFRO:    CALL    CALDIR            ; GET DIRECTORY ENTRY
  1504.     LD    A,(SEARPU)        ; TEST IF PUBLIC FILE
  1505.     LD    B,A            ; SAVE IT
  1506.     LD    A,(SEARQU)        ; TEST IF QUESTION MARK USED IN FILE NAME
  1507.     OR    B            ; A=PUBLIC FILE OR QUESTION MARK USED
  1508. CHKFR0:    LD    DE,2            ; OFFSET TO PUBLIC FILE BIT
  1509.     ADD    HL,DE            ; ADD OFFSET
  1510.     OR    A            ; TEST QUESTION MARK USED
  1511.     JR    Z,CHKFR1        ; NO THEN DON'T TEST PUBLIC FILE BIT
  1512.     BIT    7,(HL)            ; TEST PUBLIC FILE
  1513.     JR    NZ,CHKFR2        ; YES THEN ERROR
  1514. CHKFR1:    LD    E,7            ; OFFSET TO FILE R/O BIT
  1515.     ADD    HL,DE            ; ADD OFFSET
  1516.     BIT    7,(HL)            ; TEST FILE R/O
  1517.     JR    NZ,CHKFR2        ; YES THEN ERROR
  1518.     OR    A            ; TEST QUESTION MARK USED
  1519.     RET    Z            ; NO THEN DON'T TEST SYSTEM FILE BIT
  1520.     INC    HL            ; INCREMENT TO SYSTEM FILE 
  1521.     BIT    7,(HL)            ; TEST SYSTEM FILE
  1522.     RET    Z            ; NO SYSTEM FILE THEN OK
  1523. CHKFR2:    LD    HL,(SFILRO)        ; GET POINTER TO FILE R/O MESSAGE
  1524.     JP    (HL)            ; DISPLAY MESSAGE
  1525. ;
  1526. ; CHECK DRIVE READ ONLY
  1527. ;
  1528. CHKRO:    LD    HL,(DSKRO)        ; GET DRIVE R/O VECTOR
  1529.     CALL    SDRVB            ; SET DRIVE BIT
  1530.     SBC    HL,DE            ; TEST EXTRA BIT ADDED
  1531.     RET    NZ            ; YES THEN DRIVE NOT R/O
  1532.     LD    HL,(STRO)        ; GET POINTER TO DRIVE R/O MESSAGE
  1533.     JP    (HL)            ; DISPLAY MESSAGE
  1534. ;
  1535. ; GET FREE BLOCK FROM ALV BUFFER
  1536. ;  ENTRY DE=OLD BLOCK NUMBER
  1537. ;  EXIT  DE=NEW BLOCK NUMBER (0 IF NO FREE BLOCK)
  1538. ;   HL COUNTS UP,DE COUNTS DOWN
  1539. ;
  1540. GETFRE:    LD    H,D            ; COPY OLD BLOCK TO HL
  1541.     LD    L,E
  1542. GETFR0:    LD    A,D            ; TEST DOWN COUNTER IS ZERO
  1543.     OR    E
  1544.     JR    Z,GETFR1        ; YES THEN JUMP
  1545.     DEC    DE            ; DECREMEMT DOWN COUNTER
  1546.     PUSH    HL            ; SAVE UP/DOWN COUNTER
  1547.     PUSH    DE
  1548.     CALL    GETBIT            ; GET BIT FROM ALV BUFFER
  1549.     RRA                ; TEST IF ZERO
  1550.     JR    NC,GETFR3        ; YES THEN FOUND EMPTY BLOCK
  1551.     POP    DE            ; GET UP/DOWN COUNTER
  1552.     POP    HL
  1553. GETFR1:    LD    BC,(MAXLEN)        ; GET MAXIMUM ALV LENGHT-1 IN BC
  1554.     OR    A            ; CLEAR CARRY
  1555.     SBC    HL,BC            ; TEST HL>=LENGHT ALV-1
  1556.     ADD    HL,BC            ; RESTORE HL (FLAGS ARE NOT AFFECTED)
  1557.     JR    NC,GETFR2        ; END BUFFER THEN JUMP
  1558.     INC    HL            ; INCREMENT UP COUNTER
  1559.     PUSH    DE            ; SAVE DOWN/UP COUNTER
  1560.     PUSH    HL
  1561.     EX    DE,HL            ; SAVE UP COUNTER IN DE
  1562.     CALL    GETBIT            ; GET BIT FROM ALV BUFFER
  1563.     RRA                ; TEST IF ZERO
  1564.     JR    NC,GETFR3        ; YES THEN FOUND EMPTY BLOCK
  1565.     POP    HL            ; GET DOWN/UP COUNTER
  1566.     POP    DE
  1567.     JR    GETFR0            ; AND TEST NEXT BLOCK 
  1568. GETFR2:    LD    A,D            ; TEST IF LAST BLOCK TESTED
  1569.     OR    E
  1570.     JR    NZ,GETFR0        ; NO THEN TEST NEXT BLOCK
  1571.     RET                ; EXIT (DE=0)
  1572. GETFR3:    SCF                ; SET BLOCK NUMBER USED
  1573.     RLA                ; SAVE BIT
  1574.     CALL    SETBT0            ; PUT BIT IN ALV BUFFER
  1575.     POP    DE            ; GET CORRECT COUNTER
  1576.     POP    HL            ; RESTORE STACK POINTER
  1577.     RET                ; EXIT (DE=BLOCK NUMBER)
  1578. ;
  1579. ; SEARCH FOR FILE NAME
  1580. ;  ENTRY: A : NUMBER OF BYTES TO SEARCH FOR
  1581. ;
  1582. SEARCH:    LD    (SEARNB),A        ; SAVE NUMBER OF BYTES
  1583.     LD    A,0FFH            ; SET EXIT CODE TO 0FFH (NOT FOUND)
  1584.     LD    (SEAREX),A
  1585.     LD    (DCOPY),IX        ; COPY FCB POINTER TO RAM (SEARCH NEXT)
  1586.     CALL    SETFCT            ; INITIATE FILE COUNTER
  1587. ;
  1588. ; SEARCH NEXT FILE NAME
  1589. ;
  1590. SEARCN:    XOR    A            ; CHECK CHECKSUM DIRECTORY
  1591.     CALL    RDDIR            ; GET FCB FROM DIRECTORY
  1592.     CALL    TSTFCT            ; TEST IF PAST LAST ENTRY
  1593.     JP    Z,SEARC8        ; YES THEN JUMP
  1594.     LD    DE,(DCOPY)        ; GET FCB POINTER
  1595.     LD    A,(DE)            ; GET FIRST BYTE
  1596.     CP    0E5H            ; TEST IF SEARCHING EMPTY DIRECTORY
  1597.     JR    Z,SEARC1        ; YES THEN JUMP
  1598.     PUSH    DE            ; SAVE FCB POINTER
  1599.     CALL    TSTLF            ; TEST LAST FILE ON THIS DRIVE
  1600.     POP    DE            ; RESTORE FCB POINTER
  1601.     JR    NC,SEARC8        ; YES THEN JUMP
  1602. SEARC1:    CALL    CALDIR            ; GET ENTRY IN DIRECTORY
  1603.     LD    A,(HL)            ; GET FIRST BYTE DIRECTORY ENTRY
  1604.     CP    021H            ; TEST TIME STAMP
  1605.     JR    Z,SEARCN        ; YES THEN GET NEXT DIRECTORY ENTRY
  1606.     LD    A,(SEARNB)        ; GET NUMBER OF BYTES TO SEARCH FOR
  1607.     LD    B,A            ; SAVE IT IN COUNTER
  1608.     XOR    A            ; CLEAR ACCU
  1609.     LD    (SEARQU),A        ; CLEAR QUESTION MARK DETECTED FLAG
  1610.     LD    (SEARPU),A        ; CLEAR PUBLIC FILE FLAG
  1611.     RES    7,(IX+8)        ; RESET PUBLIC/SYSTEM FILE FLAG
  1612.     LD    C,A            ; CLEAR COUNTER
  1613. SEARC2:    LD    A,B            ; TEST IF COUNTER IS ZERO
  1614.     OR    A
  1615.     JR    Z,SEARC9        ; YES THEN JUMP
  1616.     LD    A,(DE)            ; GET BYTE FROM FCB
  1617.     XOR    '?'            ; TEST IF QUESTION MARK
  1618.     AND    07FH            ; MASK IT
  1619.     JR    Z,SEARC6        ; YES THEN JUMP
  1620.     LD    A,C            ; GET FCB COUNTER
  1621.     OR    A            ; TEST FIRST BYTE
  1622.     JR    NZ,SEARC3        ; NO THEN JUMP
  1623.     LD    A,(FLAGS)        ; GET FLAG BYTE
  1624.     BIT    0,A            ; TEST PUBLIC FILE ENABLE
  1625.     JR    Z,SEARC3        ; NO THEN JUMP
  1626.     INC    HL            ; GET POINTER TO PUBLIC BIT
  1627.     INC    HL
  1628.     BIT    7,(HL)            ; TEST PUBLIC BIT DIRECTORY
  1629.     DEC    HL            ; RESTORE POINTER
  1630.     DEC    HL
  1631.     JR    Z,SEARC3        ; NO PUBLIC FILE THEN JUMP
  1632.     LD    A,(DE)            ; GET FIRST BYTE FCB
  1633.     CP    0E5H            ; TEST IF SEARCHING EMPTY DIRECTORY
  1634.     JR    Z,SEARC3        ; YES THEN JUMP
  1635.     XOR    (HL)            ; TEST FCB=DIRECTORY ENTRY
  1636.     AND    07FH            ; MASK IT
  1637.     JR    Z,SEARC5        ; YES THEN JUMP
  1638.     AND    0E0H            ; MASK USER NUMBER
  1639.     JR    NZ,SEARC3        ; NOT THE SAME THEN JUMP
  1640.     DEC    A            ; A=0FFH
  1641.     LD    (SEARPU),A        ; SET PUBLIC FILE FOUND
  1642.     SET     7,(IX+8)        ; SET PUBLIC/SYSTEM FILE FLAG
  1643.     JR    SEARC5            ; JUMP FOUND
  1644. SEARC3:    LD    A,C            ; GET FCB COUNTER
  1645.     CP    13            ; TEST IF USER CODE
  1646.     JR    Z,SEARC5        ; YES THEN NO TEST
  1647.     CP    12            ; TEST IF EXTEND NUMBER
  1648.     LD    A,(DE)            ; GET BYTE FROM FCB
  1649.     JR    Z,SEARC7        ; JUMP IF EXTEND NUMBER
  1650.     XOR    (HL)            ; TEST BYTE FCB=BYTE DIRECTORY ENTRY
  1651.     AND    07FH            ; MASK IT
  1652. SEARC4:    JR    NZ,SEARCN        ; NOT THE SAME THEN GET NEXT ENTRY
  1653. SEARC5:    INC    DE            ; INCREMENT POINTER FCB
  1654.     INC    HL            ; INCREMENT POINTER DIRECTORY ENTRY
  1655.     INC    C            ; INCREMENT COUNTER
  1656.     DEC    B            ; DECREMENT COUNTER
  1657.     JR    SEARC2            ; TEST NEXT BYTE
  1658. SEARC6:    DEC    A            ; SET QUESTION MARK FOUND FLAG
  1659.     LD    (SEARQU),A        
  1660.     JR    SEARC5            ; JUMP FOUND
  1661. SEARC7:    PUSH    BC            ; SAVE COUNTERS
  1662.     XOR    (HL)            ; TEST EXTENDS
  1663.     LD    B,A            ; SAVE IT
  1664.     LD    A,(NEXTND)        ; GET EXTEND MASK
  1665.     CPL                ; COMPLEMENT IT
  1666.     AND    01FH            ; MASK IT
  1667.     AND    B            ; MASK EXTENDS
  1668.     POP    BC            ; RESTORE COUNTERS
  1669.     JR    SEARC4            ; AND TEST RESULT
  1670. SEARC8:    CALL    SETFCT            ; ERROR SET FILE COUNTER
  1671.     LD    A,0FFH            ; AND SET EXIT CODE
  1672.     LD    (PEXIT),A
  1673.     RET                ; RETURN TO CALLER
  1674. SEARC9:    LD    A,(SEARQU)        ; GET QUESTION MARK FOUND FLAG
  1675.     LD    B,A            ; SAVE IT
  1676.     LD    A,(SEARPU)        ; GET PUBLIC FILE FLAG
  1677.     AND    B            ; TEST IF PUBLIC FILE AND QUESTION MARK
  1678.     JR    NZ,SEARC4        ; YES THEN SEARCH FOR NEXT ENTRY
  1679.     CALL    SETLF            ; UPDATE LAST FILE COUNT (EMPTY FCB)
  1680.     LD    A,(FILCNT)        ; GET FILE COUNTER
  1681.     AND    3            ; MASK IT
  1682.     LD    (PEXIT),A        ; AND SET EXIT CODE
  1683.     XOR    A            ; CLEAR EXIT CODE SEARCH
  1684.     LD    (SEAREX),A
  1685.     RET                ; AND RETURN TO CALLER
  1686. ;
  1687. ; DELETE FILE
  1688. ;
  1689. DELETE:    CALL    CHKRO            ; CHECK DISK R/O
  1690.     LD    A,12            ; NUMBER OF BYTES TO SEARCH FOR
  1691.     CALL    SEARCH            ; SEARCH FILE
  1692. DEL0:    CALL    TSTFCT            ; TEST IF FILE FOUND
  1693.     RET    Z            ; NOT THEN EXIT
  1694.     CALL    CHKFRO            ; CHECK FILE R/O
  1695.     CALL    CALDIR            ; GET ENTRY POINT DIRECTORY
  1696.     LD    (HL),0E5H        ; REMOVE FILE
  1697.     LD    C,0            ; REMOVE BITS ALV BUFFER
  1698.     CALL    FILLBB 
  1699.     CALL    WRFCB            ; WRITE DIRECTORY BUFFER ON DISK
  1700.     CALL    SEARCN            ; SEARCH NEXT ENTRY
  1701.     JR    DEL0            ; AND TEST IT
  1702. ;
  1703. ; RENAME FILE
  1704. ;
  1705. RENAM:    CALL    CHKRO            ; CHECK DISK R/O
  1706.     LD    A,12            ; NUMBER OF BYTES TO SEARCH FOR
  1707.     CALL    SEARCH            ; SEARCH FILE
  1708. RENAM0:    CALL    TSTFCT            ; TEST IF FILE FOUND
  1709.     RET    Z            ; NOT THEN EXIT
  1710.     CALL    CHKFRO            ; CHECK FILE R/O
  1711.     PUSH    IX            ; SAVE FCB ENTRY
  1712.     POP    HL            ; GET IT IN HL
  1713.     LD    DE,16            ; OFFSET TO NEW NAME
  1714.     ADD    HL,DE            ; ADD OFFSET
  1715.     EX    DE,HL            ; COPY HL=>DE
  1716.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1717.     LD    B,11            ; SET UP LOOP COUNTER
  1718. RENAM1:    INC    HL            ; INCREMENT DIRECTORY POINTER
  1719.     INC    DE            ; INCREMENT FCB POINTER
  1720.     LD    A,(DE)            ; GET CHARACTER FROM FCB
  1721.     AND    07FH            ; MASK IT
  1722.     CP    '?'            ; TEST IF QUESTION MARK
  1723.     JR    Z,RENAM2        ; YES THEN DO NOT CHANGE CHARACTER ON DISK
  1724.     LD    C,A            ; SAVE IT IN C
  1725.     LD    A,(HL)            ; GET CHARACTER FROM DIRECTORY
  1726.     AND    080H            ; MASK STATUS BIT
  1727.     OR    C            ; OR WITH NEW CHARACTER
  1728.     LD    (HL),A            ; SAVE IN DIRECTORY
  1729. RENAM2:    DJNZ    RENAM1            ; LOOP UNTIL DONE
  1730.     CALL    WRFCB            ; AND WRITE DIRECTORY ON DISK
  1731.     CALL    SEARCN            ; SEARCH NEXT FILE
  1732.     JR    RENAM0            ; AND TEST IT
  1733. ;
  1734. ; CHANGE STATUS FILE
  1735. ;
  1736. CSTAT:    CALL    CHKRO            ; CHECK DISK R/O
  1737.     LD    A,12            ; NUMBER OF BYTES TO SEARCH FOR
  1738.     CALL    SEARCH            ; SEARCH FILE
  1739. CSTAT0:    CALL    TSTFCT            ; TEST IF FILE FOUND
  1740.     RET    Z            ; NOT THEN EXIT
  1741.     PUSH    IX            ; SAVE FCB ENTRY
  1742.     POP    DE            ; GET IT IN HL
  1743.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1744.     LD    B,11            ; SET UP LOOP COUNTER
  1745. CSTAT1:    INC    HL            ; INCREMENT DIRECTORY POINTER
  1746.     INC    DE            ; INCREMENT FCB POINTER
  1747.     LD    A,(DE)            ; GET STATUS BIT FROM FCB
  1748.     AND    080H            ; MASK IT
  1749.     LD    C,A            ; SAVE IT IN C
  1750.     LD    A,(HL)            ; GET CHARACTER FROM DIRECTORY
  1751.     AND    07FH            ; MASK IT
  1752.     OR    C            ; OR WITH NEW STATUS BIT
  1753.     LD    (HL),A            ; SAVE IN DIRECTORY
  1754.     DJNZ    CSTAT1            ; LOOP UNTIL DONE
  1755.     CALL    WRFCB            ; AND WRITE DIRECTORY TO DISK
  1756.     CALL    SEARCN            ; SEARCH NEXT FILE
  1757.     JR    CSTAT0            ; AND TEST IT
  1758. ;
  1759. ; COMPUTE FILE SIZE
  1760. ;
  1761. FILSZ:    LD    BC,0            ; RESET FILE SIZE LENGHT
  1762.     LD    D,C
  1763.     CALL    LDRRC            ; SAVE IT IN FCB+33,34,35
  1764.     LD    A,12            ; NUMBER OF BYTES TO SEARCH FOR
  1765.     CALL    SEARCH            ; SEARCH FILE
  1766. FILSZ0:    CALL    TSTFCT            ; TEST IF FILE FOUND
  1767.     RET    Z            ; NOT THEN EXIT
  1768.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1769.     EX    DE,HL            ; COPY TO DE
  1770.     LD    HL,15            ; OFFSET TO NEXT RECORD
  1771.     CALL    CALRRC            ; CALCULATE RANDOM RECORD COUNT
  1772.     LD    A,D            ; TEST LSB < (IX+33)
  1773.     SUB    (IX+33)
  1774.     LD    A,C            ; TEST ISB < (IX+34)
  1775.     SBC    A,(IX+34)
  1776.     LD    A,B            ; TEST MSB < (IX+35)
  1777.     SBC    A,(IX+35)
  1778.     CALL    NC,LDRRC        ; WRITE NEW MAXIMUM
  1779.     CALL    SEARCN            ; SEARCH NEXT FILE
  1780.     JR    FILSZ0            ; AND TEST IT
  1781. ;
  1782. ; WRITE FCB ON DISK
  1783. ;
  1784. WRFCB:    CALL    STDIR            ; CALCULATE SECTOR/TRACK DIRECTORY
  1785.     JP    WRITDR            ; WRITE DIRECTORY ON DISK
  1786. ;
  1787. ; FIND FILE
  1788. ;
  1789. FINDF:    LD    A,15            ; NUMBER OF BYTES TO SEARCH FOR 
  1790.     CALL    SEARCH            ; SEARCH FILE
  1791.     CALL    TSTFCT            ; TEST IF FILE PRESENT
  1792.     RET    NZ            ; YES THEN EXIT
  1793.     LD    A,(RDWR)        ; TEST IF WRITE FUNCTION
  1794.     OR    A            
  1795.     RET    NZ            ; YES THEN EXIT
  1796.     LD    A,(SEARQU)        ; TEST IF QUESTION MARK USED
  1797.     OR    A
  1798.     RET    NZ            ; YES THEN EXIT
  1799.     LD    HL,(PATH)        ; GET PATH ADDRESS
  1800.     LD    A,H            ; TEST IF ZERO (NO PATH)
  1801.     OR    L
  1802.     RET    Z            ; YES THEN EXIT
  1803. FINDF0:    LD    A,(HL)            ; GET FIRST ENTRY PATH NAME
  1804.     INC    HL            ; INCREMENT POINTER
  1805.     OR    A            ; TEST IF LAST ENTRY
  1806.     JP    Z,SEARC8        ; YES THEN ERROR EXIT 
  1807.     AND    07FH            ; MASK DRIVE NUMBER
  1808.     CP    '$'            ; TEST IF CURRENT DRIVE
  1809.     JR    NZ,FINDF1        ; NO THEN JUMP
  1810.     LD    A,(DRIVE)        ; GET CURRENT DRIVE
  1811.     INC    A            ; INCREMENT DRIVE NUMBER
  1812. FINDF1:    DEC    A            ; DECREMENT DRIVE NUMBER
  1813.     PUSH    HL            ; SAVE PATH POINTER
  1814.     CALL    SELDK            ; SELECT DRIVE
  1815.     POP    HL            ; RESTORE PATH POINTER
  1816.     LD    A,(HL)            ; GET USER NUMBER
  1817.     INC    HL            ; ADVANCE POINTER
  1818.     AND    07FH            ; MASK USER NUMBER
  1819.     CP    '$'            ; TEST IF CURRENT USER
  1820.     JR    NZ,FINDF2        ; NO THEN JUMP
  1821.     LD    A,(USER)        ; GET CURRENT USER
  1822. FINDF2:    AND    01FH            ; MASK USER NUMBER
  1823.     LD    B,A            ; SAVE IT
  1824.     LD    A,(IX+0)        ; GET FCB BYTE 0
  1825.     AND    0E0H            ; REMOVE USER NUMBER
  1826.     OR    B            ; ADD NEW USER NUMBER
  1827.     LD    (IX+0),A        ; AND SAVE IT
  1828.     PUSH    HL            ; SAVE PATH POINTER
  1829.     LD    A,15            ; SET NUMBER OF BYTES TO SEARCH FOR
  1830.     CALL    SEARCH            ; SEARCH FILE 
  1831.     CALL    TSTFCT            ; TEST IF FILE PRESENT
  1832.     POP    HL            ; RESTORE PATH POINTER
  1833.     JR    Z,FINDF0        ; NO THEN TEST NEXT PATH ENTRY
  1834.     PUSH    HL            ; SAVE PATH POINTER
  1835.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1836.     LD    DE,10            ; ADD OFFSET SYSTEM BIT
  1837.     ADD    HL,DE
  1838.     BIT    7,(HL)            ; TEST SYSTEM FILE
  1839.     POP    HL            ; RESTORE PATH POINTER
  1840.     JR    Z,FINDF0        ; NO SYSTEM FILE THEN TEST NEXT PATH ENTRY
  1841.     LD    A,(DEFDRV)        ; GET CURRENT DRIVE
  1842.     INC    A            ; INCREMENT DRIVE NUMBER
  1843.     LD    (FCB0),A        ; SAVE IT IN EXIT FCB0
  1844.     SET     7,(IX+8)        ; SET PUBLIC/SYSTEM FILE FLAG
  1845.     RET                ; AND RETURN TO CALLER
  1846. ;
  1847. ; OPEN FILE COMMAND
  1848. ;
  1849. CMND15:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  1850.     LD    (IX+14),0        ; CLEAR FCB+14
  1851. ;
  1852. ; OPEN FILE
  1853. ;
  1854. OPENF:    CALL    FINDF            ; FIND FILE (USE PATH NAME)
  1855.     CALL    TSTFCT            ; TEST FILE FOUND
  1856.     RET    Z            ; NO THEN EXIT
  1857. OPENF0:    LD    A,(IX+8)        ; GET PUBLIC/SYSTEM FILE BIT
  1858.     PUSH    AF            ; SAVE IT
  1859.     LD    A,(IX+12)        ; GET EXTEND NUMBER FROM FCB
  1860.     PUSH    AF            ; SAVE IT
  1861.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1862.     PUSH    IX            ; SAVE FCB ENTRY
  1863.     POP    DE            ; GET IN IN DE
  1864.     LD    BC,32            ; NUMBER OF BYTES TO MOVE
  1865.     LDIR                ; MOVE DIRECTORY TO FCB
  1866.     SET    7,(IX+14)        ; SET FCB/FILE NOT MODIFIED
  1867.     LD    B,(IX+12)        ; GET EXTEND NUMBER
  1868.     LD    C,(IX+15)        ; GET NEXT RECORD NUMBER
  1869.     POP    AF            ; GET OLD EXTEND NUMBER
  1870.     LD    (IX+12),A        ; SAVE IT
  1871.     CP    B            ; COMPARE OLD AND NEW EXTEND NUMBER
  1872.     JR    Z,OPENF1        ; SAME THEN JUMP
  1873.     LD    C,0            ; SET NEXT RECORD COUNT TO 0
  1874.     JR    NC,OPENF1        ; OLD EXTEND >= NEW EXTEND THEN JUMP
  1875.     LD    C,80H            ; SET NEXT RECORD COUNT TO MAXIMUM
  1876. OPENF1:    LD    (IX+15),C        ; SAVE NEXT RECORD COUNT
  1877.     POP    AF            ; GET PUBLIC/SYSTEM FILE BIT
  1878.     RL    (IX+8)            ; REMOVE MSB FROM IX+8
  1879.     RLA                ; SET NEW MSB IN CARRY
  1880.     RR    (IX+8)            ; SAVE CARRY IN IX+8
  1881.     RET                ; AND RETURN TO CALLER
  1882. ;
  1883. ; CLOSE FILE COMMAND
  1884. ;
  1885. CMND16:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  1886. ;
  1887. ; CLOSE FILE
  1888. ;
  1889. CLOSE:    BIT    7,(IX+14)        ; TEST FCB/FILE MODIFIED
  1890.     RET    NZ            ; NOT THEN NO CLOSE REQUIRED
  1891.     CALL    CHKRO            ; TEST DISK R/O
  1892.     LD    A,15            ; NUMBER OF BYTES TO SEARCH FOR
  1893.     CALL    SEARCH            ; SEARCH FILE
  1894.     CALL    TSTFCT            ; TEST FILE PRESENT
  1895.     RET    Z            ; NO THEN EXIT
  1896.     CALL    CHKFRO            ; CHECK FILE R/O
  1897.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1898.     LD    BC,16            ; OFFSET TO DM BLOCK 
  1899.     ADD    HL,BC            ; ADD OFFSET
  1900.     EX    DE,HL            ; SAVE HL IN DE
  1901.     PUSH    IX            ; SAVE FCB POINTER
  1902.     POP    HL            ; GET IT IN HL
  1903.     ADD    HL,BC            ; ADD OFFSET
  1904.     LD    A,(MAXLEN+1)        ; TEST NUMBER OF BLOCK >= 256
  1905.     OR    A            
  1906.     JR    Z,CLOSE0        ; NO THEN JUMP
  1907.     DEC    B            ; SET FLAG
  1908. CLOSE0:    CALL    COPYDM            ; COPY AND TEST BLOCKS
  1909.     EX    DE,HL            ; EXCHANGE COPY DIRECTION
  1910.     CALL    COPYDM            ; COPY AND TEST BLOCKS
  1911.     EX    DE,HL            ; EXCHANGE COPY DIRECTION
  1912.     JR    NZ,CLOSE4        ; BLOCK NOT THE SAME THEN ERROR
  1913.     INC    HL            ; INCREMENT POINTER FCB
  1914.     INC    DE            ; INCREMENT POINTER DIRECTORY
  1915.     BIT    0,B            ; TEST NUMBER OF BLOCK >= 256
  1916.     JR    Z,CLOSE1        ; NO THEN JUMP
  1917.     INC    HL            ; INCREMENT POINTER FCB
  1918.     INC    DE            ; INCREMENT POINTER DIRECTORY
  1919.     DEC    C            ; DECREMENT COUNTER
  1920. CLOSE1:    DEC    C            ; DECREMENT COUNTER
  1921.     JR    NZ,CLOSE0        ; NOT READY THEN JUMP
  1922.     LD    HL,-20            ; ADD -20 TO GET EXTEND NUMBER
  1923.     ADD    HL,DE            ; HL CONTAINS POINTER TO EXTEND NUMBER
  1924.     LD    A,(IX+12)        ; GET EXTEND NUMBER FCB
  1925.     CP    (HL)            ; COMPARE WITH EXTEND NUMBER DIRECTORY
  1926.     JR    C,CLOSE3        ; FCB < DIRECTORY THEN JUMP
  1927.     LD    (HL),A            ; SAVE EXTEND NUMBER IN DIRECTORY
  1928.     INC    HL            ; GET POINTER TO NEXT RECORD
  1929.     INC    HL
  1930.     INC    HL
  1931.     LD    A,(IX+15)        ; GET NEXT RECORD FCB
  1932. ;
  1933. ; THESE LINES HAVE TO BE REMOVED TO LET SUBMIT WORK CORRECTLY
  1934. ;
  1935. ;    JR    NZ,CLOSE2        ; EXTENDS NOT EQUAL THEN JUMP
  1936. ;    CP    (HL)            ; TEST FCB < DIRECTORY
  1937. ;    JR    C,CLOSE3        ; IF SO THEN JUMP
  1938. ;
  1939. CLOSE2:    LD    (HL),A            ; SAVE NEXT RECORD IN DIRECTORY
  1940. CLOSE3:    LD    E,5            ; SET LAST UPDATE DATE/TIME
  1941.     CALL    STIME            ; UPDATE TIME
  1942.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  1943.     LD    BC,11            ; POINT TO ARCHIEVE BYTE
  1944.     ADD    HL,BC
  1945.     RES    7,(HL)            ; RESET ARCHIEVE BIT
  1946.     RES    7,(IX+11)        ; RESET BIT IN FCB
  1947.     JP    WRFCB            ; WRITE FCB ON DISK
  1948. CLOSE4:    LD    A,0FFH            ; FLAG ERROR
  1949.     LD    (PEXIT),A 
  1950.     RET                ; AND RETURN TO CALLER
  1951. ;
  1952. ; COPY AND TEST DISK MAP
  1953. ;  ENTRY : HL : POINTER TO FIRST FCB
  1954. ;          DE : POINTER TO SECOND FCB
  1955. ;          B  : 000H LESS THEN 256 BLOCKS
  1956. ;               0FFH MORE OR EQUAL TO 256 BLOCKS
  1957. ;  EXIT  : ZERO : 1 BLOCKS ARE THE SAME
  1958. ;                 0 BLOCKS ARE NOT THE SAME
  1959. ;
  1960. COPYDM:    LD    A,(HL)            ; GET BYTE FIRST FCB
  1961.     BIT    0,B            ; TEST NUMBER OF BLOCKS >=256
  1962.     JR    Z,COPYD0        ; NO THEN JUMP
  1963.     INC    HL            ; INCREMENT POINTER
  1964.     OR    (HL)            ; TEST BYTE =0
  1965.     DEC    HL            ; DECREMENT POINTER
  1966. COPYD0:    OR    A            ; TEST BLOCK NUMBER IS ZERO
  1967.     JR    NZ,COPYD1        ; NO THEN COMPARE BLOCKS
  1968.     LD    A,(DE)            ; COPY BLOCK FROM OTHER FCB IN EMPTY LOCATION
  1969.     LD    (HL),A 
  1970.     BIT    0,B            ; TEST NUMBER OF BLOCKS >=256
  1971.     RET    Z            ; NO THEN EXIT
  1972.     INC    HL            ; INCREMENT TO MSB BLOCK NUMBERS
  1973.     INC    DE
  1974.     LD    A,(DE)            ; COPY BLOCK FROM OTHER FCB IN EMPTY LOCATION
  1975.     LD    (HL),A
  1976.     JR    COPYD2            ; JUMP TRICK TO SAVE SPACE
  1977. COPYD1:    LD    A,(DE)            ; GET BLOCK NUMBER FIRST FCB
  1978.     SUB    (HL)            ; TEST IF THE SAME
  1979.     RET    NZ            ; NOT THEN RETURN
  1980.     OR    B            ; TEST IF >=256 BLOCKS
  1981.     RET    Z            ; NO THEN RETURN
  1982.     INC    HL            ; INCREMENT TO MSB BLOCK NUMBERS
  1983.     INC    DE
  1984. COPYD2:    LD    A,(DE)            ; GET BLOCK NUMBER FIRST FCB
  1985.     SUB    (HL)            ; TEST IF THE SAME
  1986.     DEC    HL            ; DECREMENT BLOCK FCB POINTERS
  1987.     DEC    DE
  1988.     RET                ; AND EXIT TO CALLER
  1989. ;
  1990. ; MAKE FILE COMMAND
  1991. ;
  1992. CMND22:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  1993.     LD    (IX+14),0        ; CLEAR FCB+14
  1994. ;
  1995. ; MAKE FILE
  1996. ;
  1997. MAKE:    CALL    CHKRO            ; CHECK DRIVE R/O
  1998.     LD    A,(IX+0)        ; GET FIRST BYTE FCB
  1999.     PUSH    AF            ; SAVE IT
  2000.     LD    (IX+0),0E5H        ; SET FIRST BYTE TO EMPTY FILE
  2001.     LD    A,1            ; SEARCH FOR 1 BYTE
  2002.     CALL    SEARCH            ; SEARCH EMPTY FILE
  2003.     POP    AF            ; GET FIRST BYTE FCB
  2004.     LD    (IX+0),A        ; RESTORE IT
  2005.     CALL    TSTFCT            ; TEST EMPTY FILE FOUND
  2006.     RET    Z            ; NO THEN RETURN ERROR
  2007.     XOR    A            ; CLEAR FCB+13
  2008.     LD    (IX+13),A
  2009.     PUSH    IX            ; SAVE FCB POINTER
  2010.     POP    HL            ; GET IT BACK IN HL
  2011.     LD    DE,15            ; PREPARE OFFSET
  2012.     ADD    HL,DE            ; ADD IT
  2013.     LD    B,17            ; SET LOOP COUNTER
  2014. MAKE0:    LD    (HL),A            ; CLEAR FCB+15 UP TO FCB+31
  2015.     INC    HL            ; INCREMENT POINTER
  2016.     DJNZ    MAKE0            ; AND CLEAR ALL BYTES
  2017.     LD    E,1            ; SET CREATION DATE/TIME
  2018.     CALL    STIME            ; UPDATE TIME IN DIRECTORY 
  2019.     LD    E,5            ; SET LAST UPDATE DATE/TIME
  2020.     CALL    STIME            ; UPDATE TIME IN DIRECTORY
  2021.     RES    7,(IX+8)        ; RESET PUBLIC/SYSTEM FILE BIT
  2022.     RES    7,(IX+11)        ; RESET ARCHIEVE BIT IF PRESENT
  2023.     CALL    CALDIR            ; GET DIRECTORY ENTRY
  2024.     PUSH    IX            ; SAVE FCB ENTRY
  2025.     POP    DE            ; GET IT IN DE
  2026.     EX    DE,HL            ; EXCHANGE FCB AND DIRECTORY ENTRY
  2027.     LD    BC,32            ; NUMBER OF BYTES TO MOVE
  2028.     LDIR                ; MOVE BYTES
  2029.     CALL    WRFCB            ; WRITE FCB ON DISK
  2030.     SET    7,(IX+14)        ; SET FCB/FILE NOT MODIFIED
  2031.     RET                ; AND RETURN TO CALLER
  2032. ;
  2033. ; OPEN NEXT EXTEND
  2034. ;
  2035. OPENEX:    BIT    7,(IX+14)        ; TEST IF FCB/FILE MODIFIED (WRITE)
  2036.     JR    NZ,OPENX2        ; NOT THEN JUMP
  2037.     CALL    CLOSE            ; CLOSE CURRENT FCB
  2038.     LD    A,(PEXIT)        ; GET EXIT CODE
  2039.     INC    A            ; TEST IF ERROR
  2040.     RET    Z            ; YES THEN EXIT
  2041.     CALL    CALNEX            ; CALCULATE NEXT EXTEND
  2042.     JR    C,OPENX3        ; ERROR THEN JUMP
  2043.     JR    NZ,OPENX5        ; FCB PRESENT FROM CLOSE THEN JUMP
  2044. OPENX0:    LD    A,15            ; SEARCH FIRST 15 BYTES
  2045.     CALL    SEARCH            ; SEARCH FOR FILE
  2046. OPENX1:    CALL    TSTFCT            ; TEST IF FILE FOUND
  2047.     JR    NZ,OPENX5        ; YES THEN JUMP
  2048.     LD    A,(RDWR)        ; TEST READ/WRITE FLAG
  2049.     OR    A            ; TEST IF READ
  2050.     JR    Z,OPENX3        ; YES THEN ERROR
  2051.     CALL    MAKE            ; MAKE NEW EXTEND IF WRITE
  2052.     CALL    TSTFCT            ; TEST IF SUCCESFULL
  2053.     JR    NZ,OPENX6        ; YES THEN EXIT
  2054.     JR    OPENX3            ; NO THEN ERROR
  2055. OPENX2:    CALL    CALNEX            ; CALCULATE NEXT EXTEND
  2056.     JR    C,OPENX3        ; ERROR THEN JUMP
  2057.     BIT    7,(IX+10)        ; TEST SYSTEM FILE BIT
  2058.     JR    Z,OPENX0        ; NO SYSTEM FILE THEN JUMP
  2059.     CALL    FINDF            ; SEARCH PATH FOR FILE
  2060.     JR    OPENX1            ; USE SAME ROUTINE
  2061. OPENX3:    SET    7,(IX+14)        ; SET FCB/FILE NOT MODIFIED 
  2062.     LD    A,0FFH            ; SET EXIT CODE
  2063. OPENX4:    LD    (PEXIT),A        
  2064.     RET                ; AND RETURN TO CALLER
  2065. OPENX5:    CALL    OPENF0            ; OPEN FILE
  2066. OPENX6:    XOR    A            ; AND CLEAR EXIT CODE
  2067.     JR    OPENX4            ; USE SAME ROUTINE 
  2068. ;
  2069. ; CALCULATE NEXT EXTEND
  2070. ;  EXIT: CARRY=1 => OVERFLOW DETECTED
  2071. ;        ZERO =1 => SEARCH NEXT EXTEND
  2072. ;     ZERO =0 => NEXT EXTEND PRESENT (CLOSE)
  2073. ;
  2074. CALNEX:    LD    B,(IX+12)        ; GET EXTEND NUMBER
  2075.     LD    C,(IX+14)        ; GET FCB+14
  2076.     BIT    6,C            ; TEST ERROR BIT RANDOM RECORD
  2077.     SCF                ; SET ERROR FLAG
  2078.     RET    NZ            ; NON ZERO THEN ERROR EXIT
  2079.     INC    B            ; INCREMENT EXTEND NUMBER
  2080.     LD    A,B            ; GET EXTEND NUMBER
  2081.     AND    01FH            ; MASK IT
  2082.     LD    B,A            ; SAVE IT IN B
  2083.     JR    NZ,CALNX0        ; NON ZERO THEN JUMP
  2084.     INC    C            ; INCREMENT FCB+14
  2085.     LD    A,C            ; GET IT IN A
  2086.     AND    03FH            ; MASK IT
  2087.     LD    C,A            ; SAVE IT IN C
  2088.     SCF                ; SET ERROR FLAG
  2089.     RET    Z            ; AND RETURN IF FILE OVERFLOW
  2090.     XOR    A            ; CLEAR ZERO FLAG (NOT SAME EXTEND)
  2091.     JR    CALNX1            ; AND SAVE EXTEND NUMBER AND FCB+14
  2092. CALNX0:    LD    A,(NEXTND)        ; GET NEXT EXTEND MASK
  2093.     AND    B            ; TEST IF SAME EXTEND (CLOSE)
  2094. CALNX1:    LD    (IX+12),B        ; SAVE EXTEND NUMBER
  2095.     LD    (IX+14),C        ; SAVE FCB+14
  2096.     RET                ; AND RETURN TO CALLER
  2097. ;
  2098. ; READ RANDOM RECORD COMMAND
  2099. ;
  2100. CMND33:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  2101. ;
  2102. ; READ RANDOM SECTOR
  2103. ;
  2104. RDRAN:    XOR    A            ; SET READ/WRITE FLAG
  2105.     CALL    LDFCB            ; LOAD RANDOM RECORD IN FCB
  2106.     JR    Z,READS            ; NO ERROR THEN READ SECTOR
  2107.     RET                ; RETURN ERROR 
  2108. ;
  2109. ; READ SEQUENTIAL
  2110. ;
  2111. CMND20:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  2112. ;
  2113. ; READ SECTOR
  2114. ;
  2115. READS:    XOR    A            ; SET READ/WRITE FLAG
  2116.     LD    (RDWR),A        ; SAVE IT
  2117.     LD    A,(IX+32)        ; GET RECORD COUNTER
  2118.     CP    080H            ; TEST IF LAST RECORD THIS EXTEND
  2119.     JR    NC,READS1        ; YES THEN OPEN NEXT EXTEND
  2120.     CP    (IX+15)            ; TEST IF GREATER THEN CURRENT RECORD
  2121.     JR    C,READS2        ; NO THEN GET RECORD
  2122. READS0:    LD    A,1            ; SET END OF FILE FLAG
  2123.     LD    (PEXIT),A        ; SAVE IT
  2124.     RET                ; AND RETURN TO CALLER
  2125. READS1:    CALL    OPENEX            ; OPEN NEXT EXTEND
  2126.     LD    A,(PEXIT)        ; GET EXIT CODE
  2127.     OR    A
  2128.     JR    NZ,READS0        ; YES THEN END OF FILE
  2129.     LD    (IX+32),0        ; CLEAR RECORD COUNTER
  2130. READS2:    CALL    GETDM            ; GET BLOCK NUMBER FROM DM IN FCB
  2131.     LD    A,D            ; TEST BLOCK NUMBER = 0
  2132.     OR    E
  2133.     JR    Z,READS0        ; YES THEN END FILE
  2134.     CALL    CALSEC            ; CALCULATE SECTOR NUMBER (128 BYTES)
  2135.     CALL    CALST            ; CALCULATE SECTOR/TRACK NUMBER
  2136.     CALL    READR            ; READ DATA
  2137.     LD    A,(FUNCT)        ; GET FUNCTION NUMBER
  2138.     CP    20            ; TEST IF READ SEQUENTIAL
  2139.     RET    NZ            ; NO THEN RETURN
  2140.     INC    (IX+32)            ; INCREMENT NEXT RECORD COUNTER
  2141.     RET                ; AND RETURN TO CALLER
  2142. ;
  2143. ; WRITE RANDOM SECTOR WITH ZERO FILL COMMAND
  2144. ;
  2145. CMND40:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  2146. ;
  2147. ; WRITE RANDOM SECTOR WITH ZERO FILL
  2148. ;
  2149. WRRANZ:    LD    A,0FFH            ; SET READ/WRITE FLAG
  2150.     CALL    LDFCB            ; LOAD FCB FROM RANDOM RECORD
  2151.     JR    Z,WRITES        ; NO ERROR THEN WRITE RECORD
  2152.     RET                ; RETURN ERROR
  2153. ;
  2154. ; WRITE RANDOM RECORD COMMAND
  2155. ;
  2156. CMND34:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  2157. ;
  2158. ; WRITE RANDOM SECTOR
  2159. ;
  2160. WRRAN:    LD    A,0FFH            ; SET READ/WRITE FLAG
  2161.     CALL    LDFCB            ; LOAD FCB FROM RANDOM RECORD
  2162.     JR    Z,WRITES        ; NO ERROR THEN WRITE RECORD
  2163.     RET                ; RETURN ERROR
  2164. ;
  2165. ; WRITE SEQUENTIAL
  2166. ;
  2167. CMND21:    CALL    SELDRV            ; SELECT DRIVE FROM FCB
  2168. ;
  2169. ; WRITE SECTOR
  2170. ;
  2171. WRITES:    LD    A,0FFH            ; SET READ/WRITE FLAG
  2172.     LD    (RDWR),A        ; AND SAVE IT
  2173.     CALL    CHKRO            ; CHECK DISK R/O
  2174.     BIT    7,(IX+9)        ; TEST IF FILE R/O
  2175.     JP    NZ,CHKFR2        ; YES THEN FILE R/O MESSAGE
  2176.     BIT    7,(IX+8)        ; TEST IF PUBLIC OR SYSTEM FILE
  2177.     JP    NZ,CHKFR2        ; YES THEN FILE R/O MESSAGE
  2178.     LD    A,(IX+32)        ; GET RECORD COUNT
  2179.     CP    080H            ; TEST IF END THIS EXTEND
  2180.     JR    C,WRITS0        ; YES THEN OPEN NEXT EXTEND
  2181.     CALL    OPENEX            ; OPEN NEXT EXTEND
  2182.     LD    A,(PEXIT)        ; GET ERROR CODE
  2183.     OR    A        
  2184.     JP    NZ,WRITS9        ; ERROR THEN DIRECTORY FULL ERROR
  2185.     LD    (IX+32),0        ; CLEAR RECORD COUNTER
  2186. WRITS0:    CALL    GETDM            ; GET BLOCK NUMBER FROM FCB
  2187.     LD    A,D            ; TEST IF BLOCK NUMBER = 0
  2188.     OR    E
  2189.     JR    NZ,WRITS5        ; NO THEN WRITE SECTOR
  2190.     PUSH    HL            ; SAVE POINTER TO BLOCK NUMBER
  2191.     LD    A,C            ; TEST FIRST BLOCK NUMBER IN EXTEND
  2192.     OR    A
  2193.     JR    Z,WRITS1        ; YES THEN JUMP
  2194.     DEC    A            ; DECREMENT POINTER TO BLOCK NUMBER
  2195.     CALL    GETDM4            ; GET PREVIOUS BLOCKNUMBER
  2196. WRITS1:    CALL    GETFRE            ; GET NEAREST FREE BLOCK
  2197.     POP    HL            ; GET POINTER TO BLOCK NUMBER
  2198.     LD    A,D            ; TEST IF BLOCKNUMBER = 0
  2199.     OR    E
  2200.     JR    Z,WRITS8        ; YES THEN DISK FULL ERROR
  2201.     RES    7,(IX+14)        ; RESET FCB/FILE MODIFIED
  2202.     LD    (HL),E            ; SAVE BLOCKNUMBER
  2203.     LD    A,(MAXLEN+1)        ; GET NUMBER OF BLOCKS
  2204.     OR    A            ; TEST IF <256
  2205.     JR    Z,WRITS2        ; YES THEN JUMP
  2206.     INC    HL            ; INCREMENT TO MSB BLOCK NUMBER
  2207.     LD    (HL),D            ; SAVE MSB BLOCK NUMBER
  2208. WRITS2:    LD    C,2            ; SET WRITE NEW BLOCK FLAG
  2209.     LD    A,(NMASK)        ; GET SECTOR MASK
  2210.     AND    (IX+32)            ; MASK WITH RECORD COUNTER
  2211.     JR    Z,WRITSX        ; ZERO THEN OK (AT START NEW RECORD)
  2212.     LD    C,0            ; ELSE CLEAR NEW BLOCK FLAG
  2213. WRITSX:    LD    A,(FUNCT)        ; GET FUNCTION NUMBER
  2214.     SUB    40            ; TEST IF WRITE RR WITH ZERO FILL
  2215.     JR    NZ,WRITS6        ; NO THEN JUMP
  2216.     PUSH    DE            ; SAVE BLOCKNUMBER
  2217.      LD    HL,(DIRBUF)        ; USE DIRECTORY BUFFER FOR ZERO FILL
  2218.     LD    B,128            ; 128 BYTES TO CLEAR
  2219. WRITS3:    LD    (HL),A            ; CLEAR DIRECTORY BUFFER
  2220.     INC    HL            ; INCREMENT POINTER
  2221.     DJNZ    WRITS3            ; CLEAR ALL BYTES
  2222.     CALL    CALSEC            ; CALCULATE SECTOR NUMBER (128 BYTES)
  2223.     LD    A,(NMASK)        ; GET SECTOR MASK
  2224.     LD    B,A            ; COPY IT
  2225.     INC    B            ; INCREMENT IT TO GET NUMBER OF WRITES
  2226.     CPL                ; COMPLEMENT SECTOR MASK
  2227.     AND    E            ; MASK SECTOR NUMBER
  2228.     LD    E,A            ; AND SAVE IT
  2229.     LD    C,2            ; SET WRITE NEW BLOCK FLAG
  2230. WRITS4:    PUSH    HL            ; SAVE REGISTERS
  2231.     PUSH    DE
  2232.     PUSH    BC
  2233.     CALL    CALST            ; CALCULATE SECTOR/TRACK
  2234.     CALL    DMADIR            ; SET DMA DIRECTORY BUFFER
  2235.     POP    BC            ; GET WRITE NEW BLOCK FLAG
  2236.     PUSH    BC            ; SAVE IT AGAIN
  2237.     CALL    WRITER            ; WRITE RECORD ON DISK
  2238.     POP    BC            ; RESTORE REGISTERS
  2239.     POP    DE
  2240.     POP    HL
  2241.     LD    C,0            ; CLEAR WRITE NEW BLOCK FLAG
  2242.     INC    E            ; INCREMENT SECTOR NUMBER
  2243.     DJNZ    WRITS4            ; WRITE ALL BLOCKS
  2244.     CALL    STDMA            ; SET USER DMA ADDRESS
  2245.     POP    DE            ; GET BLOCK NUMBER
  2246. WRITS5:    LD    C,0            ; CLEAR WRITE NEW BLOCK FLAG 
  2247. WRITS6:    RES    7,(IX+14)        ; RESET FCB/FILE MODIFIED FLAG
  2248.     PUSH    BC            ; SAVE IT
  2249.     CALL    CALSEC            ; CALCULATE SECTOR NUMBER (128 BYTES)
  2250.     CALL    CALST            ; CALCULATE SECTOR/TRACK
  2251.     POP    BC            ; GET WRITE NEW BLOCK FLAG
  2252.     CALL    WRITER            ; WRITE RECORD ON DISK
  2253.     LD    A,(IX+32)        ; GET RECORD COUNTER
  2254.     CP    (IX+15)            ; COMPARE WITH NEXT RECORD
  2255.     JR    C,WRITS7        ; IF LESS THEN JUMP
  2256.     INC    A            ; INCREMENT RECORD COUNT 
  2257.     LD    (IX+15),A        ; SAVE IT ON NEXT RECORD POSITION
  2258.     RES    7,(IX+14)        ; RESET FCB/FILE MODIFIED FLAG
  2259. WRITS7:    LD    A,(FUNCT)        ; GET FUNCTION NUMBER
  2260.     CP    21            ; TEST WRITE SEQUENTIAL
  2261.     RET    NZ            ; NOT THEN RETURN
  2262.     INC    (IX+32)            ; INCREMENT RECORD COUNT
  2263.     RET                ; AND RETURN TO CALLER
  2264. WRITS8:    LD    A,2            ; SET DISK FULL ERROR
  2265.     LD    (PEXIT),A
  2266.     RET                ; AND RETURN TO CALLER
  2267. WRITS9:    LD    A,1            ; SET DIRECTORY FULL FLAG
  2268.     LD    (PEXIT),A
  2269.     RET                ; AND RETURN TO CALLER
  2270. ;
  2271. ; LOAD FCB FOR RANDOM READ/WRITE
  2272. ;  EXIT : ZERO FLAG : 1 NO ERROR
  2273. ;                     0 ERROR OCCURED
  2274. ;
  2275. LDFCB:    LD    (RDWR),A        ; SAVE READ/WRITE FLAG
  2276.     LD    A,(IX+33)        ; GET FIRST BYTE RANDOM RECORD
  2277.     LD    D,A            ; SAVE IT IN D
  2278.     RES    7,D            ; RESET MSB TO GET NEXT RECORD
  2279.     RLA                ; SHIFT MSB IN CARRY
  2280.     LD    A,(IX+34)        ; LOAD NEXT BYTE RANDOM RECORD
  2281.     RLA                ; SHIFT CARRY
  2282.     PUSH    AF            ; SAVE IT
  2283.     AND    01FH            ; MASK NEXT EXTEND
  2284.     LD    C,A            ; SAVE IT IN C
  2285.     POP    AF            ; GET BYTE
  2286.     RLA                ; SHIFT 4 TIMES
  2287.     RLA
  2288.     RLA
  2289.     RLA
  2290.     AND    0FH            ; MASK IT
  2291.     LD    B,A            ; SAVE FCB+14
  2292.     LD    A,(IX+35)        ; GET NEXT BYTE RANDOM RECORD
  2293.     LD    E,6            ; SET RANDOM RECORD TO LARGE FLAG
  2294.     CP    4            ; TEST RANDOM RECORD TO LARGE 
  2295.     JR    NC,LDFCB8        ; YES THEN ERROR
  2296.     RLCA                ; SHIFT 4 TIMES
  2297.     RLCA
  2298.     RLCA
  2299.     RLCA
  2300.     ADD    A,B            ; ADD BYTE
  2301.     LD    B,A            ; SAVE FCB+14 IN B
  2302.     LD    (IX+32),D        ; SET NEXT RECORD COUNT
  2303.     LD    D,(IX+14)        ; GET FCB+14
  2304.     BIT    6,D            ; TEST ERROR RANDOM RECORD
  2305.     JR    NZ,LDFCB0        ; YES THEN JUMP
  2306.     LD    A,C            ; GET NEW EXTEND NUMBER
  2307.     CP    (IX+12)            ; COMPARE WITH FCB
  2308.     JR    NZ,LDFCB0        ; NOT EQUAL THEN OPEN NEXT EXTEND
  2309.     LD    A,B            ; GET NEW FCB+14
  2310.     XOR    (IX+14)            ; COMPARE WITH FCB+14
  2311.     AND    03FH            ; MASK IT
  2312.     JR    Z,LDFCB6        ; EQUAL THEN RETURN
  2313. LDFCB0:    BIT    7,D            ; TEST FCB MODIFIED (WRITE)
  2314.     JR    NZ,LDFCB1        ; NO THEN JUMP
  2315.     PUSH    DE            ; SAVE REGISTERS
  2316.     PUSH    BC
  2317.     CALL    CLOSE            ; CLOSE EXTEND
  2318.     POP    BC            ; RESTORE REGISTERS
  2319.     POP    DE
  2320.     LD    E,3            ; SET CLOSE ERROR
  2321.     LD    A,(PEXIT)        ; GET EXIT CODE
  2322.     INC    A
  2323.     JR    Z,LDFCB7        ; ERROR THEN EXIT
  2324. LDFCB1:    LD    (IX+12),C        ; SAVE NEW EXTEND NUMBER
  2325.     LD    (IX+14),B        ; SAVE NEW FCB+14
  2326.     BIT    7,D            ; TEST FCB MODIFIED (PREVIOUS FCB)
  2327.     JR    NZ,LDFCB3        ; NO THEN JUMP
  2328. LDFCB2:    LD    A,15            ; SET NUMBER OF BYTES TO SEARCH FOR
  2329.     CALL    SEARCH            ; SEARCH NEXT FCB
  2330.     JR    LDFCB4            ; JUMP
  2331. LDFCB3:    BIT    7,(IX+10)        ; TEST IF SYSTEM FILE
  2332.     JR    Z,LDFCB2        ; NO USE SEARCH
  2333.     CALL    FINDF            ; OPEN FILE (USE PATH NAME)
  2334. LDFCB4:    LD    A,(PEXIT)        ; GET ERROR CODE
  2335.     INC    A
  2336.     JR    NZ,LDFCB5        ; NO ERROR THEN EXIT
  2337.     LD    A,(RDWR)        ; GET READ/WRITE FLAG
  2338.     LD    E,4            ; SET READ EMPTY RECORD
  2339.     INC    A
  2340.     JR    NZ,LDFCB7        ; READ THEN ERROR
  2341.     CALL    MAKE            ; MAKE NEW FCB
  2342.     LD    E,5            ; SET MAKE ERROR
  2343.     LD    A,(PEXIT)        ; GET ERROR CODE
  2344.     INC    A
  2345.     JR    Z,LDFCB7        ; ERROR THEN EXIT
  2346.     JR    LDFCB6            ; NO ERROR EXIT (ZERO SET)
  2347. LDFCB5:    CALL    OPENF0            ; OPEN FILE
  2348. LDFCB6:    XOR    A            ; SET ZERO FLAG AND CLEAR ERROR CODE
  2349.     LD    (PEXIT),A
  2350.     RET                ; AND RETURN TO CALLER
  2351. LDFCB7:    LD    (IX+14),0C0H        ; SET RANDOM RECORD ERROR
  2352. LDFCB8:    LD    A,E            ; GET ERROR CODE
  2353.     LD    (PEXIT),A        ; AND SAVE IT
  2354.     SET    7,(IX+14)        ; SET FCB/FILE NOT MODIFIED
  2355.     OR    A            ; CLEAR ZERO FLAG
  2356.     RET                ; AND RETURN TO CALLER
  2357. ;
  2358. ; CALCULATE RANDOM RECORD
  2359. ;  ENTRY HL=OFFSET IN FCB
  2360. ;        DE=FCB POINTER
  2361. ;  EXIT  D=LSB RANDOM RECORD
  2362. ;        C=ISB RANDOM RECORD
  2363. ;        B=MSB RANDOM RECORD
  2364. ;
  2365. CALRRC:    ADD    HL,DE            ; POINTER TO FCB+15 OR FCB+32
  2366.     LD    A,(HL)            ; GET BYTE
  2367.     LD    HL,12            ; OFFSET TO EXTEND NUMBER
  2368.     ADD    HL,DE            ; GET POINTER TO EXTEND BYTE
  2369.     LD    D,A            ; SAVE FIRST BYTE
  2370.     LD    A,(HL)            ; GET EXTEND BYTE
  2371.     AND    01FH            ; MASK IT
  2372.     RL    D            ; SHIFT MSB IN CARRY
  2373.     ADC    A,0            ; ADD CARRY
  2374.     RRA                ; SHIFT 1 TIME (16 BITS)
  2375.     RR    D
  2376.     LD    C,A            ; SAVE ISB
  2377.     INC    HL            ; INCREMENT TO FCB+14
  2378.     INC    HL
  2379.     LD    A,(HL)            ; GET FCB+14
  2380.     RRCA                ; SHIFT 4 TIMES
  2381.     RRCA
  2382.     RRCA
  2383.     RRCA
  2384.     PUSH    AF            ; SAVE IT
  2385.     AND    03H            ; MASK MSB
  2386.     LD    B,A            ; SAVE IT
  2387.     POP    AF            ; GET LSB
  2388.     AND    0F0H            ; MASK IT
  2389.     ADD    A,C            ; ADD WITH ISB
  2390.     LD    C,A            ; SAVE ISB
  2391.     RET    NC            ; NO CARRY THEN RETURN
  2392.     INC    B            ; INCREMENT MSB
  2393.     RET                ; AND RETURN TO CALLER
  2394. ;
  2395. ; SET TIME AND DATE
  2396. ;  ENTRY: E : 1 : SET CREATION TIME/DATE
  2397. ;             5 : SET LAST UPDATE TIME/DATE
  2398. ;  TIME RETURN POINTER IN HL
  2399. ;   HL+0 : LOW  BYTE DATE SINCE JAN,1,1978
  2400. ;   HL+1 : HIGH BYTE DATE SINCE JAN,1,1978
  2401. ;   HL+2 : HOURS   (BCD)
  2402. ;   HL+3 : MINUTES (BCD)
  2403. ;   HL+4 : SECONDS (BCD) (NOT USED IN TIME STAMP)
  2404. ;
  2405. STIME:    LD    HL,(DIRBUF)        ; GET DIRECTORY ENTRY
  2406.     LD    BC,060H            ; OFFSET ENTRY POINT TIME/DATE STAMP
  2407.     ADD    HL,BC            ; ADD OFFSET
  2408.     LD    A,(HL)            ; GET BYTE
  2409.     SUB    021H            ; TEST IF TIME STAMP PRESENT
  2410.     RET    NZ            ; NO THEN RETURN
  2411.     LD    D,A            ; CLEAR D
  2412.     ADD    HL,DE            ; ADD ENTRY (UPDATE/CREATE)
  2413.     LD    A,(SECPNT)        ; GET SECTOR POINTER
  2414.     RRCA                ; SHIFT 2 TIMES
  2415.     RRCA
  2416.     LD    E,A            ; SAVE IT
  2417.     RRCA                ; SHIFT 2 TIMES
  2418.     RRCA
  2419.     ADD    A,E            ; ADD IT (A=0,10,20)
  2420.     LD    E,A            ; SAVE IN E
  2421.     ADD    HL,DE            ; ADD OFFSET
  2422.     PUSH    HL            ; SAVE RESULT
  2423.     LD    C,0            ; RETURN POINTER IN HL
  2424.                     ; C=FF MEANS SET DATE POINTED TO BY HL
  2425.     CALL    BTIME            ; RETURN POINTER IN HL
  2426.     POP    DE            ; GET POINTER
  2427.     LD    BC,4            ; SET 4 BYTES
  2428.     LDIR                ; COPY 4 BYTES
  2429.     RET                ; AND RETURN TO CALLER
  2430. ;
  2431. ; GET TIME
  2432. ;
  2433. GETTIM:    PUSH    DE            ; SAVE ADDRESS TO PUT TIME 
  2434.     LD    C,0            ; GET TIME ADDRESS
  2435.     CALL    BTIME            ; EXECUTE P2BIOS CALL
  2436.     POP    DE            ; RESTORE ADDRESS TO PUT TIME
  2437.     LD    BC,5            ; 5 BYTES TO MOVE
  2438.     LDIR                ; STORE THE TIME
  2439.     RET                ; AND RETURN TO CALLER
  2440. ;
  2441. ; SET TIME
  2442. ;
  2443. SETTIM:    EX    DE,HL            ; GET ADDRESS TIME IN HL 
  2444.     LD    C,0FFH            ; SET TIME ADDRESS
  2445.                     ; AND FALL THROUGH TO P2BIOS CALL 
  2446. ;
  2447. ; EXECUTE P2BIOS TIME ROUTINE
  2448. ;
  2449. BTIME:    PUSH    HL            ; SAVE VALUE IN HL
  2450.     LD    HL,(TIMEAD)        ; GET ADDRESS TIME ROUTINE
  2451.     EX    (SP),HL            ; PUT ADDRESS ON STACK AND RESTORE HL
  2452.     RET                ; EXECUTE TIME ROUTINE
  2453. ;
  2454. ; P2DOS EXIT ROUTINE
  2455. ;
  2456. P2EXIT:    LD    A,(FLDRV)        ; TEST DRIVE SELECT USED FLAG
  2457.     OR    A            
  2458.     JR    Z,P2EXT0        ; NO THEN EXIT
  2459.     LD    A,(FCB0)        ; GET FCB BYTE 0
  2460.     LD    (IX+0),A        ; SAVE IT
  2461.     LD    A,(DRIVE)        ; GET OLD DRIVE NUMBER
  2462.     CALL    SELDK            ; SELECT DISK
  2463. P2EXT0:    PUSH    IX            ; SAVE IX
  2464.     POP    DE            ; RESTORE DE
  2465.     POP    IX            ; RESTORE IX
  2466.     LD    SP,(SPSAVE)        ; GET OLD SP
  2467.     LD    HL,(PEXIT)        ; GET EXIT CODE
  2468.     LD    A,(FUNCT)        ; GET FUNCTION CODE
  2469.     LD    C,A            ; RESTORE C
  2470.     LD    A,L            ; COPY FUNCTION CODE
  2471.     LD    B,H
  2472.     RET                ; AND RETURN TO CALLER
  2473. ;
  2474. ; RAM AREA
  2475. ;
  2476. TABCNT:    DEFB    0            ; TAB COUNTER
  2477. TABCX1:    DEFB    0            ; TEMPORARY TAB COUNTER (USED BY RDBUF)
  2478. FCONTP:    DEFB    0            ; LIST ENABLE FLAG (CONTROL P)
  2479. LASTCH:    DEFB    0            ; LAST CHARACTER
  2480. DELAY:    DEFB    0FFH            ; DELAY COUNTER
  2481. ;
  2482. TRANS:    DEFW    0            ; TRANSLATION VECTOR
  2483. TEMP0:    DEFW    0            ; NUMBER OF FILES ON DRIVE 
  2484. TEMP1:    DEFW    0            ; NOT USED 
  2485. TEMP2:    DEFW    0            ; NOT USED
  2486. DIRBUF:    DEFW    0            ; DIRECTORY BUFFER
  2487. IXP:    DEFW    0            ; DISK PARAMETER BLOCK
  2488. CSV:    DEFW    0            ; CHECK SUM POINTER
  2489. ALV:    DEFW    0            ; ALLOCATION VECTOR POINTER
  2490. ;
  2491. MAXSEC:    DEFW    0            ; MAXIMUM NUMBER OF SECTORS/TRACK
  2492. NBLOCK:    DEFB    0            ; NUMBER OF BLOCKS
  2493. NMASK:    DEFB    0            ; MASK NUMBER OF BLOCKS
  2494. NEXTND:    DEFB    0            ; EXTEND MASK
  2495. MAXLEN:    DEFW    0            ; MAXIMUM BLOCK NUMBER-1
  2496. NFILES:    DEFW    0            ; MAXIMUM NUMBER OF FILES-1
  2497. NDIR0:    DEFB    0            ; FIRST TWO ENTRIES ALV BUFFER
  2498. NDIR1:    DEFB    0
  2499. NCHECK:    DEFW    0            ; NUMBER OF CHECKSUM ENTRIES
  2500. NFTRK:    DEFW    0            ; FIRST TRACK NUMBER
  2501. ;
  2502. DSKRO:    DEFW    0            ; DISK R/O VECTOR
  2503. LOGIN:    DEFW    0            ; LOGIN VECTOR
  2504. DMA:    DEFW    080H            ; DMA ADDRESS
  2505. ;
  2506. FUNCT:    DEFB    0            ; FUNCTION NUMBER
  2507. PEXIT:    DEFW    0            ; EXIT CODE
  2508. FLDRV:    DEFB    0            ; DRIVE SELECT USED FLAG
  2509. RDWR:    DEFB    0            ; READ/WRITE FLAG
  2510. ;
  2511. FCB0:    DEFB    0            ; FCB BYTE 0
  2512. USER:    DEFB    0            ; USER NUMBER
  2513. DRIVE:    DEFB    0            ; DRIVE NUMBER
  2514. DEFDRV:    DEFB    0            ; DEFAULT DRIVE NUMBER
  2515. RECDIR:    DEFW    0            ; RECORD DIRECTORY (CHECKSUM)
  2516. FILCNT:    DEFW    0            ; FILE COUNTER
  2517. SECPNT:    DEFB    0            ; SECTOR POINTER
  2518. SUBFLG:    DEFB    0            ; SUBMIT FLAG (RESET DISK COMMAND)
  2519. ;
  2520. DCOPY:    DEFW    0            ; COPY ADDRESS FCB
  2521. SEAREX:    DEFB    0            ; EXIT CODE SEARCH
  2522. SEARNB:    DEFB    0            ; SEARCH NUMBER OF BYTES
  2523. SEARQU:    DEFB    0            ; SEARCH QUESTION MARK USED
  2524. SEARPU:    DEFB    0            ; SEARCH PUBLIC FILE
  2525. ;
  2526. SPSAVE:    DEFW    0            ; STACK POINTER LOCATION
  2527.     DEFS    64            ; 64 BYTES STACK
  2528. P2DOSS:                    ; P2DOS STACK
  2529. ;
  2530.     END                ; END PROGRAM
  2531.