home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol004 / findbd37.asm < prev    next >
Assembly Source File  |  1984-04-29  |  27KB  |  965 lines

  1. ;
  2. ;                   FINDBAD.ASM Ver. 3.7
  3. ;            revised 9/22/80
  4. ;
  5. ;FINDBAD WILL FIND ALL BAD BLOCKS ON A DISK AND BUILD A FILE
  6. ;NAMED [UNUSED].BAD TO ALLOCATE THEM, THUS "LOCKING OUT" THE
  7. ;BAD BLOCKS SO CP/M WILL NOT USE THEM.
  8. ;
  9. ; Originally written by Gene Cotton,  published in "Interface
  10. ;Age", September 1980 issue, page 80.
  11. ;
  12. ;THIS PROGRAM NOW SUPPORTS THE FOLLOWING DISK DRIVES:
  13. ;    - STANDARD 8" SINGLE DENSITY
  14. ;    - MICROPOLIS MOD II
  15. ;    - MICROMATION DOUBLE DENSITY
  16. ;    - DIGITAL MICROSYSTEMS FDC3 DBL DENS
  17. ;    - IMSAI DOUBLE DENSITY (IMDOS)
  18. ;    - DISCUS 2D (SINGLE SIDED) 256/512/1024 BYTE SECTORS
  19. ;
  20. ;AS PRESENTLY SET UP, THIS PROGRAM WILL PERFORM PROPERLY ON AN
  21. ;8" SINGLE DENSITY SOFT SECTORED DISK RECORDED IN STANDARD IBM
  22. ;FORMAT (I.E., 77 TRACKS, 26 SECTORS/TRACK, 243 BLOCKS/DISK, 8
  23. ;SECTORS/BLOCK, 128 BYTES/SECTOR).  IF YOUR DISK IS NOT AN IBM
  24. ;8" STANDARD, THEN YOU MUST SET THE CONDITIONAL ASSEMBLY SWITCHES
  25. ;TO ONE OF THE DEFINED DISK SYSTEMS OR MODIFY THE EXISTING DISK
  26. ;PARAMETER DEFINITIONS ACCORDING TO THE GUIDELINES ESTABLISHED
  27. ;IN THIS DOCUMENTATION.  SEE NOTES BELOW CONCERNING 'TEST'
  28. ;CONDITIONAL ASSEMBLY OPTION.
  29. ;
  30. ;NOTE: If you add conditional assembly for other disk systems,
  31. ;or otherwise update this program, please modem a copy of the
  32. ;new file to "TECHNICAL CBBS" in Dearborn, Michigan - phone
  33. ;313-846-6127 (110, 300, 450 or 600 baud).  Use the filename
  34. ;FINDBAD.NEW.   (KBP)
  35. ;
  36. ;08/06/80 ADDED COMMENTS AND CRUNCHED SOME CODE.
  37. ;      KELLY SMITH.  805-527-9321 (Modem, 300 Baud)
  38. ;            805-527-0518 (Verbal)
  39. ;
  40. ;08/26/80 MODIFIED BY KEITH PETERSEN, W8SDZ, TO:
  41. ;    (1) ADD CONDITIONAL ASSEMBLY FOR 1k/2k GROUPS
  42. ;    (2) ADD CONDITIONAL ASSEMBLY FOR STANDARD DRIVES AND
  43. ;        MICROPOLIS MOD II
  44. ;    (3) MAKE COMPATIBLE WITH CP/M-2.x
  45. ;    (4) REMOVE UNNEEDED CODE TO CHECK FOR DRIVE NAME
  46. ;        (CP/M does it for you and returns it in the FCB)
  47. ;    (5) CHANGED TO OPEN ADDITIONAL EXTENTS AS NEEDED FOR
  48. ;        OVERFLOW, INSTEAD OF ADDITIONAL FILES
  49. ;    (6) ADD CONDITIONAL ASSEMBLY FOR SYSTEM TRACKS CHECK
  50. ;        (some double-density disks have single-density
  51. ;        system tracks which cannot be read by this program)
  52. ;    (7) INCREASED STACK AREA (some systems use more than
  53. ;        others).
  54. ;
  55. ;08/27/80 FIX MISSING CONDITIONAL ASSEMBLY IN FINDB ROUTINE.
  56. ;      PUT VERSION NUMBER IN SIGN-ON MESSAGE. (KBP)
  57. ;
  58. ;08/30/80 ADDED CONDITIONAL ASSEMBLY FOR MICROMATION
  59. ;      DOUBLE DENSITY FORMAT. (CHARLES H. STROM)
  60. ;
  61. ;08/31/80 CORRECT MAXB EQUATE - MAXB MUST INCLUDE THE DIRECTORY
  62. ;      BLOCKS AS WELL AS THE DATA BLOCKS.  FIX TO MAKE SURE
  63. ;      ANY [UNUSED].BAD FILE ERASED BEFORE DATA AREA IS
  64. ;      CHECKED. (KBP)
  65. ;
  66. ;08/31/80 ADD CONDITIONAL ASSEMBLY FOR DIGITAL MICROSYSTEMS FDC3
  67. ;      CONTROLLER BOARD IN DOUBLE DENSITY FORMAT AND FIX TO
  68. ;      DO 256 BLOCKS IN ONE REGISTER. (THOMAS V. CHURBUCK)
  69. ;
  70. ;09/01/80 CHANGED EQUATES SO THAT PARAMETERS ARE AUTOMATICALLY
  71. ;      SET FOR EACH DISK SYSTEM CONDITIONAL ASSEMBLY (KBP)
  72. ;
  73. ;09/02/80 ADDED IMDOS DOUBLE-DENSITY EQUATES & MODIFIED FOR 
  74. ;      MORE THAN 256 BLOCKS PER DISK. (AL JEWER)
  75. ;
  76. ;09/08/80 FIXED SEVERAL ERRORS IN AL JEWER'S MODS.  CHANGED
  77. ;      RETURN TO CP/M TO WARM BOOT SO BITMAP IN MEMORY WILL
  78. ;      WILL BE PROPERLY UPDATED. ADDED CONDITIONAL ASSEMBLY
  79. ;      FOR TESTING PROGRAM. (KBP)
  80. ;
  81. ;09/14/80 CORRECTED DGROUP EQUATE FOR MMDBL. ADDED NEW ROUTINE
  82. ;      TO CORRECT FOR IMDOS GROUP ALLOCATION.  CORRECTED
  83. ;      ERROR IN INSTRUCTIONS FOR USING TEST ROUTINE.
  84. ;      (CHS) (AJ) (KBP) - (a group effort)
  85. ;
  86. ;09/22/80 ADDED EQUATES FOR MORROW DISK JOCKEY 2D/SS, 256,
  87. ;      512 AND 1024-BYTE SECTOR OPTIONS.  FIX 'S2' UPDATE
  88. ;      FLAG FOR LARGER MAX NUMBER OF EXTENTS. CLEANED UP
  89. ;      FILE. (BEN BRONSON and KBP)
  90. ;
  91. ;
  92. ;            Using the Program
  93. ;
  94. ; Before  using this program to "reclaim" a diskette,  it  is
  95. ;recommended that the diskette be reformatted. If this is not
  96. ;possible,  at least assure yourself that any existing  files
  97. ;on the diskette  do not contain unreadable  sectors.  If you
  98. ;have changed disks since the last warm-boot, you  must warm-
  99. ;boot again before running this program.
  100. ;
  101. ; To  use the program,  insert  both the disk containing  the
  102. ;program  FINDBAD.COM and the diskette to be checked into the
  103. ;disk drives. It is possible that the diskette containing the
  104. ;program is the one to be checked. Assume that the program is
  105. ;on drive "A" and the suspected bad disk is on drive "B".  In
  106. ;response to the CP/M prompt "A>",  type in FINDBAD B:.  This
  107. ;will  load the file FINDBAD.COM from drive "A" and test  the
  108. ;diskette  on  drive "B" for  unreadable  sectors.  The  only
  109. ;allowable  parameter  after  the  program name  is  a  drive
  110. ;specification  (of the form " N:") for up to four (A  to  D)
  111. ;disk drives.  If no drive is specified, the currently logged
  112. ;in drive is assumed to contain the diskette to check.
  113. ;
  114. ; The  program first checks the CP/M System tracks (0 and 1),
  115. ;and  any  errors here prohibit the disk from being  used  on
  116. ;drive  "A",  since all "warm boot's" occur using the  system
  117. ;tracks from the "A" drive.
  118. ;
  119. ; The  program next checks the first two data blocks  (groups
  120. ;to some of us) containing the directory of the diskette.  If
  121. ;errors  occur  here,  the  program  terminates  and  control
  122. ;returns  to  CP/M  (no other data blocks are  checked  since
  123. ;errors in the directory render the disk useless).
  124. ;
  125. ; Finally,  all  the remaining data blocks are  checked.  Any
  126. ;sectors  which  are  unreadable cause the data  block  which
  127. ;contains them to be stored temporarily as a "bad block".  At
  128. ;the end of this phase,  the message "XX bad blocks found" is
  129. ;displayed (where XX is replaced by the number of bad blocks,
  130. ;or "No" if no read errors occur).  If bad blocks occur,  the
  131. ;filname [UNUSED].BAD is created, the list of "bad blocks" is
  132. ;placed  in  the allocation map of the  directory  entry  for
  133. ;[UNUSED].BAD,  and the file is closed.  Note,  that when the
  134. ;number of "bad blocks" exceeds 16,  the  program  will  open
  135. ;additional  extents  as  required  to  hold the overflow.  I
  136. ;suggest that if the diskette has more than  32 "bad blocks",
  137. ;perhaps it should be sent to the "big disk drive in the sky"
  138. ;for the rest it deserves.
  139. ;
  140. ; The  nifty part of all this is that if any "bad blocks"  do
  141. ;occur, they are allocated to [UNUSED].BAD and no longer will
  142. ;be available to CP/M for future allocation...bad sectors are
  143. ;logically locked out on the diskette!
  144. ;
  145. ;
  146. ;              Using the TEST conditional assembly
  147. ;
  148. ;A  conditional  assembly has been added to allow  testing  this 
  149. ;program  to  make sure it is reading all sectors on  your  disk 
  150. ;that  are accessible to CP/M.  The program reads the disk on  a 
  151. ;block by block basis, so it is necessary to first determine the 
  152. ;number of blocks present.  To start, we must know the number of 
  153. ;sectors/block (8 sectors/block for standard IBM single  density 
  154. ;format).  If  this  value  is  not  known,  it  can  easily  be 
  155. ;determined  by saving one page in a test file and interrogating 
  156. ;using the STAT command:
  157. ;
  158. ;    A>SAVE 1 TEST.SIZ
  159. ;    A>STAT TEST.SIZ
  160. ;
  161. ;For standard single-density STAT will report this file as being
  162. ;1k.  The file size reported (in bytes) is the size of a  block. 
  163. ;This  value  divided  by 128 bytes/sector  (the  standard  CP/M 
  164. ;sector  size)  will  give sectors/block.  For  our  IBM  single 
  165. ;density example, we have:
  166. ;
  167. ;  (1024 bytes/block) / (128 bytes/sector) = 8 sectors/block.
  168. ;
  169. ;We  can now calculate blocks/track (assuming we know the number 
  170. ;of sectors/track). In our example:
  171. ;
  172. ;  (26 sectors/track) / (8 sectors/block) = 3.25 blocks/track
  173. ;
  174. ;Now  armed with the total number of data tracks (75 in our  IBM 
  175. ;single density example), we get toatal blocks accessible: 
  176. ;
  177. ;  75 (tracks/disk) x (3.25 blocks/track) = 243.75 blocks/disk 
  178. ;
  179. ;CP/M cannot access a fractional block, so we round down (to 243 
  180. ;blocks  in  our  example).  Now  multiplying  total  blocks  by 
  181. ;sectors/block  results in total sectors as should  be  reported 
  182. ;when TEST is set TRUE and a good disk is read. For our example, 
  183. ;this value is 1944 sectors. 
  184. ;
  185. ;Finally,  note that if SYSTEM is set TRUE,  the sectors present 
  186. ;on  the  first  two tracks must be added in  as  well.  In  the 
  187. ;previous  example,  this  results in  1944 + 52 = 1996  sectors 
  188. ;reported by the TEST conditional.
  189. ;
  190. ;Run the program on a KNOWN-GOOD disk.  It should report that it
  191. ;has read  the  correct number of sectors.  The test conditional
  192. ;assembly should then be set FALSE and the program re-assembled.
  193. ;The test routines  cannot be left in  because this program does
  194. ;not read all the sectors in a block that is found to be bad and
  195. ;thus will report an inaccurate number of sectors read.
  196. ;
  197. ;
  198. ;DEFINE TRUE AND FALSE
  199. ;
  200. FALSE    EQU    0
  201. TRUE    EQU    NOT FALSE
  202. ;
  203. ;******************************************************************
  204. ;CONDITIONAL ASSEMBLY SWITCHES (only one should be true)
  205. ;
  206. STDDRV    EQU    TRUE     ;TRUE IF STANDARD 8" SINGLE DENSITY DRIVE
  207. MICROP    EQU    FALSE    ;TRUE IF MICROPOLIS MOD II
  208. MMDBL    EQU    FALSE    ;TRUE IF MICROMATION DOUBLE DENSITY
  209. DIGDBL    EQU    FALSE    ;TRUE IF DIGITAL MICROSYSTEMS FDC3 DBL DENS
  210. IMDOS    EQU    FALSE     ;TRUE IF IMSAI DOUBLE DENSITY
  211. DJ256S    EQU    FALSE    ;TRUE IF MORROW 2D/SS(256-BYTE SECTOR)
  212. DJ512S    EQU    FALSE    ;TRUE IF MORROW 2D/SS(512-BYTE SECTOR)
  213. DJ1024    EQU    FALSE    ;TRUE IF MORROW 2D/SS(1024-BYTE SECTOR)
  214. ;******************************************************************
  215. ;
  216. ;CONDITIONAL ASSEMBLY SWITCH FOR TESTING THIS PROGRAM
  217. ;(for initial testing phase only - see remarks above)
  218. ;
  219. TEST    EQU    FALSE    ;TRUE FOR TESTING ONLY
  220. ;******************************************************************
  221. ;
  222. ;SYSTEM EQUATES
  223. ;
  224. BASE    EQU    0    ;STANDARD CP/M BASE ADDRESS
  225. BDOS    EQU    BASE+5    ;CP/M WARM BOOT ENTRY
  226. FCB    EQU    BASE+5CH;CP/M DEFAULT FCB LOCATION
  227. ;
  228. ;DEFINE DISK SYSTEM PARAMETERS
  229. ;
  230.     IF    STDDRV
  231. SYSTEM    EQU    TRUE    ;TRUE IF CHECK SYSTEM TRACKS WANTED
  232. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  233. SECTS    EQU    26    ;TOTAL NUMBER OF SECTORS/TRACK
  234. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  235. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  236. MAXB    EQU    243    ;MAX NUMBER OF BLOCKS (including directory)
  237. BLOCK    EQU    8    ;NUMBER OF SECTORS/BLOCK
  238. DGROUP    EQU    FALSE    ;TRUE IF 2k GROUP SIZE
  239.     ENDIF        ;STDDRV
  240. ;
  241.     IF    MICROP
  242. SYSTEM    EQU    TRUE    ;TRUE IF CHECK SYSTEM TRACKS WANTED
  243. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  244. SECTS    EQU    32    ;TOTAL NUMBER OF SECTORS/TRACK
  245. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  246. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  247. MAXB    EQU    150    ;MAX NUMBER OF BLOCKS (including directory)
  248. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  249. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  250.     ENDIF        ;MICROP
  251. ;
  252.     IF MMDBL
  253. SYSTEM    EQU    FALSE    ;FALSE IF CHECK SYSTEM TRACKS NOT WANTED
  254. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  255. SECTS    EQU    52    ;TOTAL NUMBER OF SECTORS/TRACK
  256. DBASE    EQU    2    ;DATA AREA STARTING TRACK NUMBER
  257. BBASE    EQU    2    ;FIRST BLOCK FOR DATA
  258. MAXB    EQU    243    ;MAXIMUM NUMBER OF BLOCKS (including directory)
  259. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  260. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  261.     ENDIF        ;MMDBL
  262. ;
  263.     IF    DIGDBL
  264. SYSTEM    EQU    FALSE    ;FALSE IF CHECK SYSTEM TRACKS NOT WANTED
  265. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  266. SECTS    EQU    58    ;TOTAL NUMBER OF SECTORS/TRACK
  267. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  268. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  269. MAXB    EQU    256    ;MAXIMUM NUMBER OF BLOCKS (including directory)
  270. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  271. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  272.     ENDIF        ;DIGDBL
  273. ;
  274.     IF    IMDOS
  275. SYSTEM    EQU    FALSE    ;TRUE IF CHECK SYSTEM TRACKS WANTED
  276. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  277. SECTS    EQU    58    ;TOTAL NUMBER OF SECTORS/TRACK
  278. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  279. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  280. MAXB    EQU    271    ;MAX NUMBER OF BLOCKS (including directory)
  281. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  282. DGROUP    EQU    TRUE     ;TRUE IF 2k GROUP SIZE
  283.     ENDIF        ;IMDOS
  284. ;
  285.     IF    DJ256S
  286. SYSTEM    EQU    FALSE    ;FALSE IF CHECK SYSTEM TRACKS NOT WANTED
  287. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  288. SECTS    EQU    52    ;TOTAL NUMBER OF SECTORS/TRACK
  289. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  290. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  291. MAXB    EQU    243    ;MAXIMUM NUMBER OF BLOCKS (including directory)
  292. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  293. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  294.     ENDIF        ;MORROW DJ256S
  295. ;
  296.     IF    DJ512S
  297. SYSTEM    EQU    FALSE    ;FALSE IF CHECK SYSTEM TRACKS NOT WANTED
  298. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  299. SECTS    EQU    60    ;TOTAL NUMBER OF SECTORS/TRACK
  300. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  301. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  302. MAXB    EQU    281    ;MAXIMUM NUMBER OF BLOCKS (including directory)
  303. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  304. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  305.     ENDIF        ;MORROW DJ512S
  306. ;
  307.     IF    DJ1024
  308. SYSTEM    EQU    FALSE    ;FALSE IF CHECK SYSTEM TRACKS NOT WANTED
  309. TRACKS    EQU    77    ;TOTAL NUMBER OF TRACKS/DISK
  310. SECTS    EQU    64    ;TOTAL NUMBER OF SECTORS/TRACK
  311. DBASE    EQU    2    ;DIRECTORY & DATA AREA STARTING TRACK NUMBER
  312. BBASE    EQU    2    ;FIRST BLOCK NUMBER FOR DATA
  313. MAXB    EQU    300    ;MAXIMUM NUMBER OF BLOCKS (including directory)
  314. BLOCK    EQU    16    ;NUMBER OF SECTORS/BLOCK
  315. DGROUP    EQU    TRUE    ;TRUE IF 2k GROUP SIZE
  316.     ENDIF        ;MORROW DJ1024
  317. ;
  318. ;DEFINE ASCII CHARACTERS USED
  319. ;
  320. CR    EQU    0DH    ;ASCII CARRIAGE RETURN CHARACTER
  321. LF    EQU    0AH    ;ASCII LINE FEED CHARACTER
  322. TAB    EQU    09H    ;ASCII TAB CHARACTER
  323. ;
  324. ;
  325.     ORG    BASE+100H
  326. ;
  327. START:    LXI    SP,NEWSTK ;MAKE NEW STACK
  328. ;
  329.     IF    IMDOS
  330.     XRA    A
  331.     OUT    0FFH    ;CLEAR FRONT PANEL
  332.     ENDIF        ;IMDOS
  333. ;
  334.     LXI    D,IDMSG    ;IDENT MESSAGE
  335.     CALL    START2    ;GO PRINT IT
  336. ;
  337. IDMSG:    DB    CR,LF,'FINDBAD - ver 3.7'
  338.     DB    CR,LF,'Bad sector lockout '
  339.     DB    'program',CR,LF
  340. ;
  341.     IF    STDDRV
  342.     DB    'For single-density 8" only'
  343.     ENDIF
  344. ;
  345.     IF    MICROP
  346.     DB    'For Micropolis Mod II only'
  347.     ENDIF
  348. ;
  349.     IF    MMDBL
  350.     DB    'For Micromation double-density only'
  351.     ENDIF
  352. ;
  353.     IF    DIGDBL
  354.     DB    'For Digital Microsystems',CR,LF
  355.     DB    'FDC3 cntlr dbl dens only'
  356.     ENDIF
  357. ;
  358.     IF    IMDOS
  359.     DB    'For IMSAI IMDOS double-density ONLY'
  360.     ENDIF
  361. ;
  362.     IF    DJ256S
  363.     DB    'For Discus 2-dens./1-side/256-byte sectors only'
  364.     ENDIF
  365. ;
  366.     IF    DJ512S
  367.     DB    'For Discus 2-dens./1-side/512-byte sectors only'
  368.     ENDIF
  369. ;
  370.     IF    DJ1024
  371.     DB    'For Discus 2-dens./1-side/1024-byte sectors only'
  372.     ENDIF
  373. ;
  374.     DB    CR,LF,'$'
  375. ;
  376. START2    POP    D    ;GET MSG ADRS
  377.     MVI    C,9    ;BDOS PRINT BUFFER FUNCTION
  378.     CALL    BDOS    ;PRINT SIGN-ON MSG
  379.     CALL    IBIOS    ;SET BIOS ENTRY, AND CHECK DRIVE
  380.     CALL    FINDB    ;ESTABLISH ALL BAD BLOCKS
  381.     JZ    NOBAD    ;SAY NO BAD BLOCKS, IF SO
  382.     CALL    OPENB    ;OPEN [UNUSED].BAD ALLOCATION
  383.     CALL    SETDM    ;FIX DM BYTES IN FCB
  384.     CALL    CLOSEB    ;CLOSE [UNUSED].BAD
  385.     CALL    SETNUM    ;PUT NUMBER OF BAD BLOCKS IN MESSAGE
  386. ;
  387. NOBAD:    LXI    D,ENDMSG;SAY HOW MANY BAD BLOCKS
  388. ;
  389. PMSG:    MVI    C,9    ;BDOS PRINT BUFFER FUNCTION
  390.     CALL    BDOS
  391. ;
  392.     IF    TEST
  393.     MVI    A,TAB    ;GET A TAB
  394.     CALL    TYPE    ;PRINT IT
  395.     LHLD    SECCNT    ;GET NUMBER OF SECTORS READ
  396.     CALL    DECOUT    ;PRINT IT
  397.     LXI    D,SECMSG ;POINT TO MESSAGE
  398.     MVI    C,9    ;BDOS PRINT BUFFER FUNCTION
  399.     CALL    BDOS    ;PRINT IT
  400.     ENDIF        ;TEST
  401. ;
  402.     IF    IMDOS
  403.     XRA    A
  404.     OUT    0FFH    ;CLEAR FRONT PANEL
  405.     ENDIF        ;IMDOS
  406. ;
  407.     JMP    BASE    ;EXIT TO CP/M WARM BOOT
  408. ;
  409. ;GET ACTUAL ADDRESS OF BIOS ROUTINES
  410. ;
  411. IBIOS:    LHLD    BASE+1    ;GET BASE ADDRESS OF BIOS VECTORS
  412. ;
  413. ;WARNING...PROGRAM MODIFICATION TAKES PLACE HERE...DO NOT CHANGE!
  414. ;
  415.     LXI    D,27    ;OFFSET TO "SETTRK"
  416.     DAD    D
  417.     SHLD    SETTRK+1;FIX OUR CALL ADDRESS
  418.     LXI    D,3    ;OFFSET TO "SETSEC"
  419.     DAD    D
  420.     SHLD    SETSEC+1;FIX OUR CALL ADDRESS
  421.     LXI    D,6    ;OFFSET TO "DREAD"
  422.     DAD    D
  423.     SHLD    DREAD+1    ;FIX OUR CALL ADDRESS
  424. ;
  425. ;CHECK FOR DRIVE SPECIFICATION
  426. ;
  427.     LDA    FCB    ;GET DRIVE NAME
  428.     ORA    A    ;ZERO?
  429.     RZ        ;YES, NO DRIVE CHANGE REQUIRED
  430.     CPI    4+1    ;CHECK FOR HIGHEST DRIVE NUMBER
  431.     JNC    ERROR4
  432.     DCR    A    ;BACK OFF FOR CP/M
  433.     MOV    E,A    ;MAKE DISK NUMBER
  434.     MVI    C,14    ;BDOS SELECT DISK FUNCTION
  435.     CALL    BDOS
  436.     RET        ;RETURN FROM "IBIOS"
  437. ;
  438. ;LOOK FOR BAD BLOCKS
  439. ;
  440. FINDB:    EQU    $
  441. ;
  442.     IF    SYSTEM
  443.     CALL    CHKSYS    ;CHECK FOR BAD BLOCKS ON TRACK 0 AND 1
  444.     ENDIF        ;SYSTEM
  445. ;
  446.     CALL    CHKDIR    ;CHECK FOR BAD BLOCKS IN DIRECTORY
  447.     CALL    ERAB    ;ERASE ANY [UNUSED].BAD FILE
  448.     LXI    B,BBASE    ;START AT FIRST DATA BLOCK
  449. ;
  450. FINDBA:    CALL    READB    ;READ THE BLOCK
  451.     CNZ    SETBD    ;IF BAD, ADD BLOCK TO LIST
  452.     INX    B    ;BUMP TO NEXT BLOCK
  453.     MOV    A,C    ;SEE IF MORE TO CHECK
  454.     CPI    MAXB AND 0FFH
  455.     JNZ    FINDBA
  456.     MOV    A,B    ;THEN CHECK HI BYTE
  457.     CPI    MAXB SHR 8
  458.     JNZ    FINDBA    ;LOOP TILL DONE    
  459.     LHLD    DMCNT    ;GET NUMBER OF BAD SECTORS
  460.     MOV    A,H
  461.     ORA    L    ;SET ZERO FLAG, IF NO BAD BLOCKS
  462.     RET        ;RETURN FROM "FINDB"
  463. ;
  464.     IF    SYSTEM
  465. ;
  466. ;CHECK SYSTEM TRACKS, NOTIFY USER IF BAD...BUT CONTINUE
  467. ;
  468. CHKSYS:    LXI    H,1    ;SET TRACK 0, SECTOR 1
  469. ;
  470. CHKSY1:    CALL    READS    ;READ A SECTOR
  471.     JNZ    SYSERR    ;NOTIFY, IF BAD BLOCKS HERE
  472.     MOV    A,H    ;BOTH SYSTEM TRACKS DONE?
  473.     CPI    2
  474.     JC    CHKSY1
  475.     RET        ;RETURN FROM "CHKSYS"
  476. ;
  477. SYSERR:    LXI    D,ERMSG5;SAY NO GO, AND BAIL OUT
  478.     MVI    C,9    ;BDOS PRINT BUFFER FUNCTION
  479.     CALL    BDOS
  480.     RET        ;RETURN FROM "SYSERR"
  481. ;
  482.     ENDIF        ;SYSTEM
  483. ;
  484. ;CHECK FOR BAD BLOCKS IN DIRECTORY AREA
  485. ;
  486. CHKDIR:    LXI    B,0    ;START AT BLOCK 0
  487. ;
  488. CHKDI1:    CALL    READB    ;READ A BLOCK
  489.     JNZ    ERROR6    ;IF BAD, INDICATE ERROR IN DIRECTORY AREA
  490.     INX    B    ;BUMP FOR NEXT BLOCK
  491.     MOV    A,C    ;GET BLOCK NUMBER
  492.     CPI    BBASE    ;ALL DONE CHECKING DIRECTORY AREA?
  493.     JC    CHKDI1    ;PRESS ON, IF NOT
  494.     RET        ;RETURN FROM "CHKDIR"
  495. ;
  496. ;READ ALL SECTORS IN BLOCK, AND RETURN ZERO FLAG SET IF NONE BAD
  497. ;
  498. READB:    CALL    CNVRTB    ;CONVERT TO TRACK/SECTOR IN H&L REGS.
  499.     MVI    D,BLOCK    ;NUMBER OF SECTORS/BLOCK
  500. ;
  501. READBA:    PUSH    D
  502.     CALL    READS    ;READ SKEWED SECTOR
  503.     POP    D
  504.     RNZ        ;ERROR IF NOT ZERO...
  505.     DCR    D    ;DEBUMP SECTOR/BLOCK
  506.     JNZ    READBA    ;DO NEXT, IF NOT FINISHED
  507.     RET        ;RETURN FROM "READBA"
  508. ;
  509. ;CONVERT BLOCK NUMBER TO TRACK AND SKEWED SECTOR NUMBER
  510. ;
  511. CNVRTB:    PUSH    B    ;SAVE BLOCK NUMBER
  512.     MOV    L,C    ;BLOCK NUMBER TO H&L REGS.
  513.     MOV    H,B
  514.     DAD    H    ;*2
  515.     DAD    H    ;*4
  516.     DAD    H    ;*8
  517. ;
  518.     IF    DGROUP
  519.     DAD    H    ;*16 FOR 2k GROUP SIZE
  520.     ENDIF        ;DGROUP
  521. ;
  522.     LXI    D,DBASE*256    ;MAKE BASE TRACK NUMBER
  523.     LXI    B,-SECTS    ;DIVIDE BY SECTORS/TRACK
  524. ;
  525. CNVRTC:    MOV    A,H    ;OVER SECTORS...
  526.     ORA    A
  527.     JNZ    CNVRTT    ;...BYE GROUPS?
  528.     MOV    A,L    ;OVER SECTORS...
  529.     CPI    SECTS
  530.     JC    CNVRTS    ;...AND DOWN TO TRACKS?
  531. ;
  532. CNVRTT:    DAD    B    ;TAKE AWAY SECTORS
  533.     INR    D    ;+1 TO TRACK NUMBER
  534.     JMP    CNVRTC    ;...AND GO BACK FOR MORE
  535. ;
  536. CNVRTS:    MOV    E,L    ;RESIDUAL = SKEWED SECTOR-1
  537.     INR    E    ;BUMP FOR SECTORS 1 TO 32
  538.     XCHG        ;TRACK/SECTOR IN H&L REGS.
  539.     POP    B    ;RECOVER BLOCK NUMBER
  540.     RET        ;RETURN FROM "CNVRTB"
  541. ;
  542. ;READS A LOGICAL SECTOR (IF IT CAN), AND RETURNS ZERO FLAG SET IF NO ERROR
  543. ;
  544. READS:    PUSH    B    ;EXILE BLOCK
  545.     PUSH    H    ;...AND TRACK/SECTOR
  546.     CALL    LTOP    ;CONVERT LOGICAL TO PHYSICAL SECTOR
  547.     PUSH    H    ;SAVE SECTOR NUMBER
  548.     MOV    C,H    ;TRACK NUMBER IN H REG...
  549. ;
  550. SETTRK:    CALL    $-$    ;BIOS SET TRACK (MODIFIED BY IBIOS)
  551.     POP    B    ;PUT SECTOR IN C
  552. ;
  553. SETSEC:    CALL    $-$    ;BIOS SET SECTOR (MODIFIED BY IBIOS)
  554. ;
  555. DREAD:    CALL    $-$    ;BIOS READ SECTOR (MODIFIED BY IBIOS)
  556.     ORA    A    ;SET FLAGS FOR POSSIBLE BAD SECTOR
  557. ;
  558.     IF    TEST
  559.     LHLD    SECCNT    ;GET NUMBER OF SECTORS READ
  560.     INX    H    ;INCREMENT
  561.     SHLD    SECCNT    ;SAVE NEW NUMBER
  562.     ENDIF        ;TEST
  563. ;
  564.     POP    H
  565.     POP    B    ;BACK FROM EXILE...
  566.     PUSH    PSW    ;SAVE FLAGS
  567.     INR    L    ;BUMP FOR NEXT SECTOR
  568.     MOV    A,L
  569.     CPI    SECTS+1    ;TRACK OVERFLOW?
  570.     JC    READSR
  571.     MVI    L,1    ;YUP, RESET SECTOR NUMBER TO 1...
  572.     INR    H    ;...AND BUMP TRACK NUMBER
  573. ;
  574. READSR:    POP    PSW    ;GET FLAGS, TO CHECK IF ERROR ON RETURN
  575.     RET        ;RETURN FROM "READS"
  576. ;
  577. ;CONVERT LOGICAL TO PHYSICAL SECTOR
  578. ;
  579. LTOP:    XCHG
  580.     LXI    B,LPMAP-1 ;GET BASE OF LOGICAL TO PHYSICAL MAPPING
  581.     MOV    L,E
  582.     MVI    H,0    ;LOGICAL SECTOR OFFSET
  583.     DAD    B    ;+ BIAS
  584.     MOV    E,M    ;GET PHYSICAL SECTOR
  585.     XCHG        ;PUT H&L REGS. BACK...
  586.     RET        ;RETURN FROM "LTOP"
  587. ;
  588. ;LOGICAL TO PHYSICAL MAPPING VECTORS (SECTOR SKEW TABLE)
  589. ;
  590.     IF    STDDRV
  591. LPMAP:    DB    01,07,13,19,25,05,11,17,23,03,09,15,21
  592.     DB    02,08,14,20,26,06,12,18,24,04,10,16,22
  593.     ENDIF        ;STDDRV
  594. ;
  595.     IF    MICROP
  596. LPMAP:    DB    01,02,11,12,21,22,31,32,09,10,19,20,29,30,07,08
  597.     DB    17,18,27,28,05,06,15,16,25,26,03,04,13,14,23,24
  598.     ENDIF        ;MICROP
  599. ;
  600.     IF    MMDBL
  601. LPMAP:    DB    01,14,27,40,10,23,36,49,06,19,32,45,02,15,28,41
  602.     DB    11,24,37,50,07,20,33,46,03,16,29,42,12,25,38,51
  603.     DB    08,21,34,47,04,17,30,43,13,26,39,52,09,22,35,48
  604.     DB    05,18,31,44
  605.     ENDIF        ;MMDBL
  606. ;
  607.     IF    DIGDBL
  608. LPMAP:    DB    01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16
  609.     DB    17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
  610.     DB    33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
  611.     DB    49,50,51,52,53,54,55,56,57,58
  612.     ENDIF        ;DIGDBL
  613. ;
  614.     IF    IMDOS
  615. LPMAP:    DB    1,8,15,22,29,36,43,50,57,6,13,20,27,34,41,48,55
  616.     DB    4,11,18,25,32,39,46,53,2,9,16,23,30,37,44,51,58
  617.     DB    7,14,21,28,35,42,49,56,5,12,19,26,33,40,47,54
  618.     DB    3,10,17,24,31,38,45,52
  619.     ENDIF        ;IMDOS
  620. ;
  621.     IF    DJ256S
  622. LPMAP:    DB    01,02,19,20,37,38,03,04,21,22,39,40,05,06,23,24
  623.     DB    41,42,07,08,25,26,43,44,09,10,27,28,45,46,11,12
  624.     DB    29,30,47,48,13,14,31,32,49,50,15,16,33,34,51,52
  625.     DB    17,18,35,36
  626.     ENDIF        ;DJ256S
  627. ;
  628.     IF    DJ512S
  629. LPMAP:    DB    01,02,03,04,17,18,19,20,33,34,35,36,49,50,51,52
  630.     DB    05,06,07,08,21,22,23,24,37,38,39,40,53,54,55,56
  631.     DB    09,10,11,12,25,26,27,28,41,42,43,44,57,58,59,60
  632.     DB    13,14,15,16,29,30,31,32,45,46,47,48
  633.     ENDIF        ;DJ512S
  634. ;
  635.     IF    DJ1024
  636. LPMAP:    DB    01,02,03,04,05,06,07,08,25,26,27,28,29,30,31,32
  637.     DB    49,50,51,52,53,54,55,56,09,10,11,12,13,14,15,16
  638.     DB    33,34,35,36,37,38,39,40,57,58,59,60,61,62,63,64
  639.     DB    17,18,19,20,21,22,23,24,41,42,43,44,45,46,47,48
  640.     ENDIF        ;DJ1024
  641. ;
  642. ;PUT BAD BLOCK IN BAD BLOCK LIST
  643. ;
  644. SETBD:    LHLD    DMCNT    ;GET NUMBER OF SECTORS
  645.     LXI    D,BLOCK
  646.     DAD    D    ;BUMP BY NUMBER IN THIS BLOCK
  647.     SHLD    DMCNT    ;UPDATE NUMBER OF SECTORS
  648.     LHLD    DMPTR    ;GET POINTER INTO DM
  649.     MOV    M,C    ;...AND PUT BAD BLOCK NUMBER
  650.     INX    H    ;BUMP TO NEXT AVAILABLE EXTENT
  651. ;
  652.     IF    IMDOS OR DJ512S OR DJ1024
  653.     MOV    M,B    ;PUT IN 2ND BYTE FOR IMDOS OR DJ512/1024
  654.     INX    H    ;POINT TO NEXT AVAILABLE EXTENT
  655.     ENDIF        ;IMDOS OR DJ512S OR DJ1024
  656. ;
  657.     SHLD    DMPTR    ;SAVE DM POINTER, FOR NEXT TIME THROUGH HERE
  658.     RET        ;RETURN FROM "SETBD"
  659. ;
  660. ;ELIMINATE ANY PREVIOUS [UNUSED].BAD ENTRIES
  661. ;
  662. ERAB:    LXI    D,BFCB    ;POINT TO BAD FCB
  663.     MVI    C,19    ;BDOS DELETE FILE FUNCTION
  664.     CALL    BDOS
  665.     RET
  666. ;
  667. ;CREATE [UNUSED].BAD FILE ENTRY
  668. ;
  669. OPENB:    LXI    D,BFCB    ;POINT TO BAD FCB
  670.     PUSH    D    ;SAVE IT...
  671.     MVI    C,22    ;BDOS MAKE FILE FUNCTION
  672.     CALL    BDOS
  673.     POP    D    ;RECOVER BAD FCB POINTER
  674.     MVI    C,15    ;BDOS OPEN FILE FUNCTION
  675.     CALL    BDOS
  676.     CPI    0FFH    ;CHECK FOR OPEN ERROR
  677.     RNZ        ;RETURN FROM "OPENB", IF NO ERROR
  678.     JMP    ERROR7    ;BAIL OUT...CAN'T CREATE [UNUSED].BAD
  679. ;
  680. ;MOVE BAD AREA DM TO BFCB
  681. ;
  682. SETDM:    LXI    H,DM    ;GET DM
  683.     SHLD    DMPTR    ;SAVE AS NEW POINTER
  684.     LHLD    DMCNT    ;GET THE COUNT
  685. ;
  686. SETDM0:    MOV    A,H
  687.     ORA    A
  688.     JNZ    GOBIG
  689.     MOV    A,L
  690.     CPI    129    ;ALL BYTES MOVED?
  691.     JC    SETDME
  692. ;
  693. GOBIG:    LXI    D,-128
  694.     DAD    D
  695.     PUSH    H
  696.     MVI    A,128
  697.     CALL    SETDME
  698.     XCHG
  699.     SHLD    DMPTR
  700.     CALL    CLOSEB    ;CLOSE OLD EXTENT
  701.     LDA    EXTNUM    ;GET OLD EXTENT NUMBER
  702.     INR    A    ;INCREMENT IT
  703.     STA    EXTNUM    ;SAVE NEW EXTENT NUMBER
  704.     STA    BFCB+12    ;PUT NEW EXTENT NUMBER INTO OUR FCB
  705.     CALL    OPENB    ;OPEN NEW EXTENT
  706.     POP    H
  707.     JMP    SETDM0
  708. ;
  709. SETDME:    STA    BFCB+15    ;PUT RC IN PLACE
  710. ;
  711.     IF    NOT DGROUP
  712.     MVI    B,16    ;NUMBER OF BYTES TO MOVE
  713.     ENDIF        ;NOT DGROUP
  714. ;
  715.     IF    DGROUP
  716.     MVI    B,8    ;NUMBER OF BYTES TO MOVE
  717.     ENDIF        ;DGROUP
  718. ;
  719.     LHLD    DMPTR    ;GET BAD DMAP POINTER
  720.     XCHG        ;TO DE
  721.     LXI    H,BFCB+16 ;POINT AT OUR FCB
  722. ;
  723. SETDML:    EQU    $
  724. ;
  725.     IF    NOT IMDOS
  726.     LDAX    D    ;GET BYTE FROM DMAP
  727.     MOV    M,A    ;MOVE TO OUR FCB
  728.     INX    D    ;INCREMENT DMAP POINTER
  729.     INX    H    ;INCREMENT OUR FCB POINTER
  730.     ENDIF        ;NOT IMDOS (1 BYTE GROUP #)
  731. ;
  732.     IF    DJ512S OR DJ1024
  733.     LDAX    D    ;GET SECOND BYTE FROM DMAP
  734.     MOV    M,A    ;MOVE TO OUR FCB
  735.     INX    D    ;INCREMENT DMAP POINTER
  736.     INX    H    ;INCREMENT OUR FCB POINTER
  737.     ENDIF        ;DJ512S OR DJ1024 (2 BYTE GROUP #)
  738. ;
  739.     IF    IMDOS
  740.     LDAX    D    ;GET FIRST (LO ORDER) BYTE FROM DMAP
  741.     MOV    C,A    ;SAVE IT IN C
  742.     INX    D    ;INCREMENT DMAP POINTER
  743.     LDAX     D    ;THEN GET SECOND (HI ORDER) BYTE
  744.     MOV    M,A    ;STORE HI BYTE FIRST
  745.     INX    H    ;INCREMENT FCB POINTER
  746.     MOV    M,C    ;THEN LO BYTE FOR 16-BIT POINTER
  747.     INX    H    ;INCREMENT OUR FCB POINTER
  748.     ENDIF        ;IMDOS (2 BYTE GROUP #)
  749. ;
  750.     DCR    B    ;ONE LESS BYTE TO MOVE
  751.     JNZ    SETDML    ;NOT DONE, GO MOVE MORE
  752.     RET        ;ELSE RETURN FROM "SETDM"
  753.  
  754. ;
  755. CLOSEB:    XRA    A
  756.     LDA    BFCB+14    ;GET CP/M 2.x 'S2' BYTE
  757.     ANI    1FH    ;ZERO UPDATE FLAGS
  758.     STA    BFCB+14    ;RESTORE IT TO OUR FCB (WON'T HURT 1.4)
  759.     LXI    D,BFCB    ;FCB FOR [UNUSED].BAD
  760.     MVI    C,16    ;BDOS CLOSE FILE FUNCTION
  761.     CALL    BDOS
  762.     RET        ;RETURN FROM "CLOSEB"
  763. ;
  764. ;CONVERT NUMBER OF BLOCKS TO DECIMAL ASCII, FOR PRINTING
  765. ;
  766. SETNUM:    LHLD    DMCNT    ;GET NUMBER OF SECTORS
  767.     DAD    H    ;*2
  768.     DAD    H    ;*4
  769.     DAD    H    ;*8
  770.     DAD    H    ;*16
  771. ;
  772.     IF    NOT DGROUP
  773.     DAD    H    ;*32 FOR 1k GROUP SIZE
  774.     ENDIF
  775. ;
  776. ;H REG NOW EQUALS NUMBER OF BLOCKS
  777.     LXI    D,255
  778.     DAD    D    ;ROUND UP
  779.     MOV    L,H
  780.     MVI    H,0    ;NOW H&L REGS. EQUAL NUMBER OF BLOCKS
  781.     LXI    D,NUMBAD
  782.     CALL    DCNV
  783.     RET        ;RETURN FROM "SETNUM"
  784. ;
  785. DCNV:    MVI    B,' '    ;SET FOR PLUS
  786.     MOV    A,H
  787.     ORA    A
  788.     JP    H3
  789.     MVI    B,'-'
  790.     MOV    A,L
  791.     CMA
  792.     INR    A
  793.     MOV    L,A
  794.     MOV    A,H
  795.     CMA
  796.     JNZ    H2
  797.     INR    A
  798. ;
  799. H2:    MOV    H,A
  800. ;
  801. H3:    SHLD    DCNVHL
  802.     MVI    A,' '
  803.     STAX    D
  804.     MOV    A,B
  805.     STA    DCNVPM
  806.     XCHG
  807.     SHLD    DCNVAD
  808.     XRA    A
  809.     STA    DCNVFL
  810.     LXI    B,-10000
  811.     CALL    DFL8
  812.     CALL    DSTC
  813.     LXI    B,-1000
  814.     CALL    DFL8
  815.     CALL    DSTC
  816.     LXI    B,-100
  817.     CALL    DFL8
  818.     CALL    DSTC
  819.     LXI    B,-10
  820.     CALL    DFL8
  821.     CALL    DSTC
  822.     LDA    DCNVHL
  823.     ORI    '0'
  824.     MOV    E,A
  825. ;
  826. DSTC:    LHLD    DCNVAD
  827.     LDA    DCNVFL
  828.     ORA    A
  829.     JNZ    DSTC3
  830. ;
  831. DSTC1:    ADD    E
  832.     STA    DCNVFL
  833.     JNZ    DSTC2
  834.     MVI    A,' '
  835.     JMP    DSTC4
  836. ;
  837. DSTC2:    LDA    DCNVPM
  838.     MOV    M,A
  839. ;
  840. DSTC3:    MVI    A,'0'
  841.     ORA    E
  842. ;
  843. DSTC4:    INX    H
  844.     MOV    M,A
  845.     SHLD    DCNVAD
  846.     RET        ;RETURN FROM "SETDM"
  847. ;
  848. DCNVFL:    DB    0
  849. DCNVHL:    DW    0
  850. DCNVAD:    DW    0
  851. DCNVPM:    DB    0
  852. ;
  853. DFL8:    LHLD    DCNVHL
  854.     MVI    E,0
  855. ;
  856. DF1:    DAD    B
  857.     MOV    A,H
  858.     ORA    A
  859.     RM
  860.     INR    E
  861.     SHLD    DCNVHL
  862.     JMP    DF1
  863. ;
  864. BFCB:    DB    0,'[UNUSED]BAD',0,0,0,0
  865.     DS    17
  866. ;
  867. ENDMSG:    DB    CR,LF,'    '
  868. ;
  869. NUMBAD:    DB    '    No'
  870.     DB    ' bad blocks found',CR,LF,'$'
  871. ;
  872. EXTNUM:    DB    0    ;USED IF MORE THAN 16 BAD BLOCKS
  873. DMCNT:    DW    0    ;NUMBER OF BAD SECTORS
  874. DMPTR:    DW    DM    ;POINTER TO NEXT BLOCK ID
  875. ;
  876. ;ALLOCATION MAP FOR BAD BLOCKS
  877. ;
  878. DM:    DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  879.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  880.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  881.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  882.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  883.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  884.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  885.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  886.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  887.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  888.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  889.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  890.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  891.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  892.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  893.     DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  894. ;
  895. ;ERROR MESSAGES
  896. ;
  897. ERROR4:    LXI    D,ERMSG4 ;SAY NO GO, AND BAIL OUT
  898.     JMP    PMSG
  899. ;
  900. ERMSG4:    DB    CR,LF,'Only drives A to D allowed$'
  901. ;
  902.     IF    SYSTEM
  903. ERMSG5:    DB    CR,LF,'Warning...System tracks bad$'
  904.     ENDIF        ;SYSTEM
  905. ;
  906. ERROR6:    LXI    D,ERMSG6 ;OOPS...CLOBBERED DIRECTORY
  907.     JMP    PMSG
  908. ;
  909. ERMSG6:    DB    CR,LF,'Bad directory area, try reformatting$'
  910. ;
  911. ERROR7:    LXI    D,ERMSG7 ;SAY NO GO, AND BAIL OUT
  912.     JMP    PMSG
  913. ;
  914. ERMSG7:    DB    CR,LF,'Can''t create [UNUSED].BAD$'
  915. ;
  916.     IF    TEST
  917. ;
  918. ;DECIMAL OUTPUT ROUTINE
  919. ;
  920. DECOUT:    PUSH    B
  921.     PUSH    D
  922.     PUSH    H
  923.     LXI    B,-10
  924.     LXI    D,-1
  925. ;
  926. DECOU2:    DAD    B
  927.     INX    D
  928.     JC    DECOU2
  929.     LXI    B,10
  930.     DAD    B
  931.     XCHG
  932.     MOV    A,H
  933.     ORA    L
  934.     CNZ    DECOUT
  935.     MOV    A,E
  936.     ADI    '0'
  937.     CALL    TYPE
  938.     POP    H
  939.     POP    D
  940.     POP    B
  941.     RET
  942. ;
  943. TYPE:    PUSH    B
  944.     PUSH    D
  945.     PUSH    H
  946.     MOV    E,A    ;CHARACTER TO E FOR CP/M
  947.     MVI    C,2    ;PRINT CONSOLE FUNCTION
  948.     CALL    BDOS    ;PRINT CHARACTER
  949.     POP    H
  950.     POP    D
  951.     POP    B
  952.     RET
  953. ;
  954. SECMSG:    DB    ' total sectors read',CR,LF,'$'
  955. ;
  956. SECCNT:    DW    0    ;NUMBER OF SECTORS READ
  957. ;
  958.     ENDIF        ;TEST
  959. ;
  960.     DS    60    ;ROOM FOR 30 LEVEL STACK
  961. NEWSTK    EQU    $    ;OUR STACK
  962. ;
  963.     END
  964.  
  965.