home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm68k / msutils.lbr / SD.SQ / SD.S
Encoding:
Text File  |  1988-02-18  |  48.1 KB  |  1,729 lines

  1. *#######################################################################
  2. *             Program SD...Directory Utility
  3. *
  4. *                          Dr. David C. Wilcox
  5. *                          DCW Industries, Inc.
  6. *                 5354 Palm Drive, La Canada, CA  91011
  7. *                             818/790-3844
  8. *
  9. *                            April 13, 1986
  10. *#######################################################################
  11. *
  12. * SPECIAL NOTE:
  13. * =============
  14. * This sorted directory utility has been created by translating the
  15. * CP/M-80 utility of the same name created by Bruce Ratliff from 8080
  16. * mnemonics to MC68000 mnemonics.  I did the original work on a TRS-80
  17. * Model 16 with CP/M 68k running on top of CP/M Plus.  Since CP/M Plus
  18. * supports time and date stamping, I chose to display time and date
  19. * stamps via special CP/M 68k bios calls to read the CP/M Plus time and
  20. * date stamp information.  I have added a trs80 conditional assembly
  21. * flag which should exclude all such calls, but I have no way of testing
  22. * to see if I've done it correctly.  Please let me know if there are
  23. * any problems and I'll try to provide fixes.
  24. *                                 D.C. Wilcox
  25. *#######################################################################
  26. * Special registers:
  27. *
  28. *    a5 = address of dma buffer
  29. *    a6 = address of 1st parsed fcb
  30. *#######################################################################
  31. *
  32. false    equ    0
  33. true    equ    $ff
  34. *
  35. * user option specifications
  36. *
  37. aopt    equ    true     *true to allow searching all user areas
  38. dopt    equ    true      *true to allow searching all drives on-line
  39. nopt    equ    true    *true to allow disabling page pause option
  40. popt    equ    true    *true to allow printer option
  41. ropt    equ    true    *true to allow nonarchived file option
  42. sopt    equ    true     *true to allow system file option
  43. uopt    equ    true    *true to allow user number option
  44. *
  45. truek    equ    true    *true to display actual file size
  46. trs80    equ    false    *true if TRS-80 Model 16 with CP/M Plus
  47. *
  48. break    equ    03    *ascii etx (^C)
  49. tab    equ    09    *horizontal tab
  50. lf    equ    10    *line feed
  51. cr    equ    13    *carriage return
  52. xoff    equ    19    *ascii dc3 (^S)
  53. esc    equ    27    *ascii escape
  54. space    equ    32    *ascii space
  55. marker    equ    33    *time/date stamping indicator
  56. upmask    equ    $5f    *upper case mask
  57. *
  58. *delim    equ    124    *fence (delimiter) character (vertical bar)
  59. delim    equ    32    *space
  60. *delim    equ    58    *colon
  61. *
  62. npl    equ    02    *# of names per line (max of 2 for 80x24)
  63. margsz    equ    10    *width of left margin indent
  64. lps    equ    23    *# of lines per screen (max of 23 for 80x24)
  65. *
  66. drvmax    equ    07    *maximum drive number (0=a:,1=b:...,7=h:)
  67. usrmax    equ    15    *maximum user number (0-15)
  68. stskip    equ    04    *start skipping at this drive number (1=a:,...)
  69. skipto  equ    09    *and skip to this drive number (1=a:,...)
  70. *
  71. * bdos equates
  72. *
  73. boot    equ    00    *warm boot
  74. rdchr    equ    01    *read character from console
  75. wrchr    equ    02    *write character to console
  76. listout    equ    05    *output to LST:
  77. dirio    equ    06    *direct console I/O
  78. pstring    equ    09    *print a string
  79. const    equ    11    *check console status
  80. seldsk    equ    14    *select    disk
  81. search    equ    17    *search for first
  82. next    equ    18    *search for next
  83. curdsk    equ    25    *get currently logged disk name
  84. setdma    equ    26    *set current dma
  85. curdpb    equ    31    *get current disk parameters
  86. curusr    equ    32    *get currently logged user number
  87. getfree    equ    46    *get disk free space
  88. calbios    equ    50    *direct bios call
  89. z80r    equ    $85    *read  Z80 memory
  90. *
  91. bdos    equ    $0002    *bdos entry point
  92. bios    equ    $0003    *bios entry point
  93. *
  94. * Locate fcb and dma (for portability)
  95. *
  96.     link    a6,#0        *mark stack frame
  97.     move.l    8(a6),a0    *get base page address
  98.     lea    $80(a0),a5    *get address of dma buffer
  99.     lea    $5c(a0),a6    *get address of 1st parsed file name
  100.     jsr    clear        *Make sure key registers are clear
  101. start:
  102.     move.w    #$ff,d1        *get current user number
  103.     move.w    #curusr,d0
  104.     trap    #bdos
  105.     move.b    d0,oldusr    *initialize startup user number
  106.     move.b    d0,newusr    *..and make new    user match it
  107.     ifne    dopt
  108.     move.b    d0,basusr    *save extra copy for multi-disk
  109.     endc            *directories
  110.     move.w    #curdsk,d0
  111.     trap    #bdos        *get current disk nr
  112.     move.b    d0,olddsk    *save for reset    if needed
  113. *
  114. * First we parse the dma to see if a user number has been entered.
  115. * If so, the fcb and dma are rewritten in normal CP/M syntax.
  116. *
  117.     jsr    parse
  118. *
  119. * Check to see if the fcb drive spec matches the currently logged
  120. * drive.  If so, put a zero in the fcb since it's redundant.
  121. *
  122.     jsr    setdflt
  123. *
  124. * If at    least one option is allowed, scan the command line for the
  125. * option field delimiter.  Any unrecognized options or illegal user
  126. * numbers will cause the help message to print.  (Note that we scan the
  127. * command line buffer rather than the 2nd default fcb because all 7
  128. * options plus a 2 digit user number won't fit in the fcb name field).
  129. *
  130. * Search for command line delimiter.  If not found, assume no options.
  131. *
  132.     clr.l    d2
  133.     movea.l    a5,a2        *set command line buffer pointer
  134.     move.b    (a2)+,d2    *get length of command line buffer
  135. scndol:
  136.     subq.b    #1,d2
  137.     blt    ckrest        *exit if command line buffer empty
  138.     move.b    (a2)+,d0
  139.     cmpi.b    #'[',d0        *option delimiter = "["
  140.     bne    scndol
  141. *
  142. * Valid    delimiter found.  Scan the rest    of the buffer for options.
  143. * Errors past this point cause an abort.
  144. *
  145. scnopt:
  146.     subq.b    #1,d2        *dock characters left in option    field
  147.     blt    ckrest        *if option field exhausted, exit
  148. scnagn:    move.b    (a2)+,d0    *get the next option character
  149.     cmpi.b    #space,d0    *do we have a space?
  150.     beq    scnopt        *ignore    it if so
  151.     cmpi.b    #',',d0        *same for comma
  152.     beq    scnopt
  153.     cmpi.b    #']',d0        *end of option list
  154.     beq    ckrest
  155.     movea.l    #otbl,a0    *get base of option lookup table
  156.     subq    #1,a0
  157.     move.l    #oend,a1    *get length of option lookup table
  158.     suba.l    a0,a1
  159.     move.l    a1,d1
  160. nomach:    addq    #1,a0        *bump to next option table character
  161.     subq.b    #1,d1        *are we    out of the table?
  162.     beq    ck4usr        *if so, check for user option
  163.     cmp.b    (a0),d0        *compare our character with option table
  164.     bne    nomach        *exit if no match
  165.     move.b    #0,(a0)        *otherwise, activate the flag
  166.     bra    scnopt        *..and go get the next option character
  167. *
  168. * If option character doesn't match the table, see if we have a user
  169. * option.
  170. *
  171. ck4usr:    nop
  172.     ifne    uopt        *check for user    number option
  173.     cmpi.b    #'U',d0
  174.     bne    clerr        *last option
  175. uagn:    subq    #1,d2        *bump to user number digit
  176.     blt    clerr        *error if nothing left
  177.     move.b    (a2)+,d0    *get decimal digit
  178.     cmpi.b    #space,d0    *ignore    leading    spaces
  179.     beq    uagn
  180.     subi.b    #$30,d0        *subtract ascii    bias
  181.     blt    clerr        *error if < 0
  182.     cmpi.b    #10,d0
  183.     bgt    clerr        *error if > 9
  184.     move.b    d0,newusr    *save user number as it    may be 1 digit
  185.     ifne    dopt
  186.     move.b    d0,basusr    *duplicate it if multi-disk mode
  187.     move.b    #$ff,gotusr    *set got user flag
  188.     endc
  189.     subq.b    #1,d2        *bump to possible 2nd digit of user no.
  190.     blt    ckrest        *if no more buffer, exit with user #
  191.     move.b    (a2),d0        *else, check for another digit
  192.     subi.b    #$30,d0
  193.     blt    scnagn        *if next char not numeric, it's not part
  194.     cmpi.b    #10,d0        *of user no. so check for another option
  195.     bgt    scnagn
  196.     movea.l    #newusr,a1    *get tens digit
  197.     move.b    (a1),d1
  198.     mulu    #10,d1        *multiply by 10
  199.     add.b    d1,d0        *combine with units digit
  200.     move.b    d0,(a1)        *save the total    user number
  201.     addq    #1,a2        *point to next option
  202.     ifne    dopt
  203.     move.b    d0,basusr    *duplicate it if multi-disk mode
  204.     endc
  205.     bra    scnopt        *continue scanning
  206.     endc            *balance uopt
  207. *
  208. * If command line error    occurs, say so and display instructions on
  209. * correct usage.
  210. *
  211. clerr:
  212.     movea.l    #synerr,a0    *display "syntax error" in reverse video
  213.     jsr    print
  214.     bra    help        *..and display help message
  215. *
  216. * Options input or not specified.  Get today's date & time before
  217. * proceeding any further.
  218. *
  219. ckrest:    nop
  220.     ifne    trs80
  221.     jsr    today
  222.     endc
  223. *
  224. * If "A" option choosen and no user number specified
  225. * set user to zero
  226. *
  227. zusr:    nop
  228.     ifne    aopt
  229.     movea.l    #gotusr,a0    *was a user specified?
  230.     cmpi.b    #0,(a0)
  231.     bne    zdrv        *yes-quit now
  232.     movea.l    #aopflg,a0    *was "A" option specified?
  233.     cmpi.b    #0,(a0)
  234.     bne    zdrv        *branch if no
  235.     move.b    #0,newusr    *zero newusr for all users
  236.     ifne    dopt
  237.     move.b    #0,basusr    *zero basusr for all users
  238.     endc
  239.     endc
  240. *
  241. * If "D" option choosen and no drive specified
  242. * set drive to physical zero
  243. *
  244. zdrv:    move.b    (a6),d0        *get drive name    for directory search
  245.     cmpi.b    #0,d0        *any specified?
  246.     bne    noopt        *skip next routine if drive specified
  247.     ifne    dopt
  248.     movea.l    #dopflg,a0    *else if dopt then
  249.     cmpi.b    #0,(a0)
  250.     bne    zdrv1
  251.     move.b    #1,(a6)        *always start with a:
  252.     bra    noopt
  253.     endc
  254. zdrv1:    movea.l    #olddsk,a0    *otherwise, get    default    disk
  255.     move.b    (a0),d0
  256.     addq.b    #1,d0
  257.     move.b    d0,(a6)        *put the absolute drive    code in    fcb
  258. *
  259. * Validate drive code and user area number.
  260. *
  261. noopt:    movea.l    #dremsg,a0    *get the drive/user error message
  262.     move.b    (a6),d0        *get directory drive code
  263.     subq.b    #1,d0        *normalize to range of 0-7
  264.     cmpi.b    #drvmax,d0    *compare with maximum drives on-line
  265.     bgt    erxit        *take drive error exit if out of range
  266.     movea.l    #usrmsg,a0    *switch    to user    # error    message
  267.     movea.l    #maxusr,a1
  268.     move.b    #usrmax,(a1)    *store max user # in maxusr
  269.     movea.l    #newusr,a1    *point to the directory    user area
  270.     move.b    (a1),d0
  271.     cmpi.b    #usrmax,d0    *compare it with the maximum
  272.     bgt    erxit        *take error exit if user number    illegal
  273.     movea.l    a6,a1        *point to first character in fcb
  274.     addq    #1,a1
  275.     cmpi.b    #'[',(a1)
  276.     beq    gotdl
  277.     cmpi.b    #space,(a1)
  278.     bne    gotfcb
  279. *
  280. * If no fcb...make fcb all '?'
  281. *
  282. gotdl:    moveq.l    #11,d2        *fn+ft count
  283. qloop:    move.b    #'?',(a1)+    *store '?' in fcb
  284.     subq    #1,d2
  285.     bne    qloop
  286. gotfcb:    move.b    #'?',12(a6)    *force wild extent
  287.     jsr    setsrc        *set dma for bdos media change check
  288.     move.b    (a6),d1        *get the drive code out of the fcb
  289.     subq    #1,d1        *normalize drive code for select
  290.     move.b    #seldsk,d0    *select the directory drive to retrieve
  291.     trap    #bdos        *..the proper allocation vector
  292.     move.l    #cdpb,d1    *request dpb
  293.     move.w    #curdpb,d0
  294.     trap    #bdos
  295. *
  296. * Calculate # of kbytes free on selected drive
  297. *
  298. free:    clr.l    d1
  299.     move.b    (a6),d1        *get drive #
  300.     subq    #1,d1
  301.     move.w    #getfree,d0    *use compute free space bdos call
  302.     trap    #bdos
  303.     move.l    (a5),d0
  304.     divu    #8,d0        *convert from sectors to kbytes
  305.     move.w    d0,freeby    *save free space for output later
  306. *
  307. * Check for presence of time and date stamps
  308. *
  309.     move.b    #2,mnpl        *reset column counter to 2
  310.     jsr    chkstmp        *check for date/time stamps
  311.     movea.l    #stampon,a0
  312.     cmp.b    #$20,(a0)    *are they present?
  313.     beq    settbl        *yes...stay with 2 column display
  314.     move.b    #3,mnpl        *no....change to a 3 column display
  315. *
  316. * Reenter here on subsequent passes while in the all-users mode
  317. *
  318. settbl:    clr.l    d2
  319.     movea.l    #dirmax,a0    *get directory maximum again
  320.     move.w    (a0),d2
  321.     addq.w    #1,d2        *directory size    is dirmax+1
  322.     mulu    #4,d2        *quadruple directory size
  323.     movea.l    #order,a1    *to get    size of    order table
  324.     add.l    d2,a1        *allocate order    table
  325.     movea.l    #tbloc,a0    *name table begins where
  326.     move.l    a1,(a0)
  327.     move.l    a1,nextt    *order table begins
  328.     ifne    uopt
  329.     clr.l    d1
  330.     movea.l    #newusr,a0    *get user area for directory
  331.     move.b    (a0),d1
  332.     move.w    #curusr,d0    *get the user function
  333.     trap    #bdos        *..and set new user number
  334.     endc
  335. *
  336. * Look up the fcb in the directory
  337. *
  338. sfirst:    move.w    #0,count    *initialize match counter
  339.     move.w    #0,totfil    *initialize total file counter
  340.     move.w    #0,totsiz    *initialize total size counter
  341.     jsr    setsrc        *set dma for directory search
  342.     move.w    #search,d0    *get 'search first' function
  343.     bra    look        *..and go search for 1st match
  344. *
  345. * Read more directory entries
  346. *
  347. mordir:    move.w    #next,d0    *search    next
  348. look:    move.l    a6,d1
  349.     trap    #bdos        *read directory    entry
  350.     cmpi.b    #$ff,d0        *check for end ($ff)
  351.     beq    sprint        *if no more, sort & print what we have
  352. *
  353. * Point    to directory entry
  354. *
  355. some:    move.b    d0,tdflag    *save it for retrieving date stamp
  356.     mulu    #32,d0        *compute directory offset
  357.     movea.l    a5,a2        *point to dma buffer
  358.     add.l    d0,a2        *point to entry
  359.     adda.l    #10,a2        *point to sys byte
  360.     ifne    ropt
  361.     movea.l    #ropflg,a0    *did user request unarchived
  362.     cmpi.b    #0,(a0)        *files only?
  363.     bne    anyarc
  364.     adda.l    #1,a2        *point to arc byte
  365.     btst    #7,(a2)        *check bit 7 of arc byte
  366.     bne    mordir        *skip if it's archived
  367.     suba.l    #1,a2        *now point to sys bit for proper
  368.     bra    sysfok        *alignment...then skip sys bit check
  369.     endc
  370. anyarc:    nop
  371.     ifne    sopt
  372.     movea.l    #sopflg,a0    *did user request sys files?
  373.     move.b    (a0),d0
  374.     cmpi.b    #0,d0
  375.     beq    sysfok
  376.     endc
  377.     btst    #7,(a2)        *check bit 7 of sys byte
  378.     bne    mordir        *skip that file
  379. sysfok:    suba    #10,a2        *back to user number (alloc flag)
  380.     movea.l    #newusr,a0    *get current user
  381.     cmpm.b    (a0)+,(a2)+
  382.     bne    mordir        *ignore    if different
  383. *
  384. * Move entry to    table
  385. *
  386.     movea.l    #nextt,a0    *next table entry to...
  387.     move.l    (a0),a3        *register a3
  388.     moveq.l    #12,d2        *entry length (name, type, extent)
  389. tmove:    move.b    (a2)+,(a3)+    *store entry character in table
  390.     subq    #1,d2        *more?
  391.     bne    tmove
  392.     adda    #2,a2        *point to sector count
  393.     move.b    (a2)+,(a3)+    *store in table
  394.     cmpi.b    #$20,stampon    *check for date stamp enabled
  395.     beq    savdat        *enabled...so retrieve date stamp
  396.     adda    #5,a3        *otherwise, skip over five bytes
  397.     bra    tmove1
  398. savdat:    movea.l    #tdflag,a0    *fetch fcb number
  399.     clr.l    d0
  400.     move.b    (a0),d0
  401.     mulu    #10,d0        *calculate time/date stamp offset
  402.     addi.b    #101,d0
  403.     movea.l    a5,a2        *point to beginning of dma buffer
  404.     add    d0,a2        *add time/date stamp offset
  405.     moveq.l    #4,d2
  406. loopdat:move.b    (a2)+,(a3)+    *copy time/date stamp data
  407.     subq    #1,d2        *in table
  408.     bne    loopdat
  409.     move.b    #0,(a3)+    *pad with a null byte
  410. tmove1:    move.l    a3,nextt    *save updated table addr
  411.     addq.w    #1,count    *bump the # of matches made
  412.     bra    mordir
  413. *
  414. * Sort and print
  415. *
  416. sprint:    nop
  417.     ifne    aopt or uopt
  418.     jsr    setfop        *return to file output dma & user #
  419.     endc
  420.     movea.l    #count,a0    *get file name count
  421.     movea.l    #tcount,a4
  422.     move.w    (a0)+,(a4)+
  423.     cmpi.w    #0,tcount    *any found?
  424.     beq    prtotl        *exit if no files found
  425.     move.b    #1,supspc    *enable    leading    zero suppression
  426.     subq    #2,a4        *make a4 point to tcount
  427. *
  428. * Initialize the order table
  429. *
  430.     movea.l    #tbloc,a0    *get start of name table
  431.     move.l    (a0),a2
  432.     movea.l    #order,a1    *point to order    table
  433. bldord:    move.l    a2,(a1)+    *save address
  434.     adda    #18,a2        *point to next entry (add 18 bytes)
  435.     subq    #1,(a4)        *count down loop
  436.     bne    bldord        *if nonzero, do another one
  437.     movea.l    #count,a0    *get count
  438.     move.w    (a0),scount    *save as # to sort
  439.     cmpi.b    #1,(a0)        *only 1    entry?
  440.     beq    noout        *yes, so skip sort
  441. *
  442. * This sort routine is adapted from (8080) software tools
  443. * by Kernigan and Plaugher.  I'm sure it can be improved
  444. * upon, and has probably been written for the MC68000 long
  445. * ago...BUT...each day only has 24 hours!  I simply translated
  446. * the 8080 routine.
  447. *
  448. sort:    clr.l    d0
  449.     clr.l    d1
  450.     clr.l    d4
  451.     movea.l    #scount,a3    *number    of entries
  452. l0:    clr.l    d3        *clear carry
  453.     move.w    (a3),d3        *gap=gap/2
  454.     divu    #2,d3
  455.     cmpi.w    #0,d3        *is it zero?
  456.     beq    noout        *then none left
  457.     ori.b    #1,d3        *make gap odd
  458.     move.w    d3,gap
  459.     addq.w    #1,d3        *i=gap+1
  460. l2:    move.w    d3,i
  461.     movea.l    #gap,a3
  462.     move.w    (a3),d4        *j=i-gap
  463.     sub.w    d4,d3
  464. l3:    move.w    d3,j
  465.     movea.l    #gap,a3        *jg=j+gap
  466.     move.w    (a3),d4
  467.     add.w    d3,d4
  468.     move.w    d4,jg
  469.     move.w    d4,d0
  470.     move.w    d3,d1
  471.     jsr    compare        *compare (j) and (jg)
  472.     bgt    l5        *if a(j)<=a(jg)
  473.     movea.l    #j,a3
  474.     move.w    (a3),d0
  475.     movea.l    #jg,a3
  476.     move.w    (a3),d1
  477.     jsr    swap        *exchange a(j) and a(jg)
  478.     movea.l    #j,a3        *j=j-gap
  479.     move.w    (a3),d3
  480.     movea.l    #gap,a3
  481.     move.w    (a3),d4
  482.     sub.w    d4,d3
  483.     blt    l5        *if j>0    goto l3
  484.     cmpi.w    #0,d3        *check for zero
  485.     beq    l5
  486.     bra    l3
  487. l5:    movea.l    #scount,a3    *for later
  488.     move.w    (a3),d4
  489.     movea.l    #i,a3        *i=i+1
  490.     move.w    (a3),d3
  491.     addq.w    #1,d3
  492.     cmp.w    d3,d4        *if i<=n goto l2
  493.     bge    l2
  494.     movea.l    #gap,a3
  495.     bra    l0
  496. *
  497. * Sort is all done - print entries
  498. *
  499. noout:
  500.     movea.l    #order,a3    *initialize order table    pointer
  501.     move.l    a3,nextt
  502.     jsr    crlf        *print "directory for ...
  503.     movea.l    #dirms1,a0    *at start of each section
  504.     jsr    print
  505.     jsr    prdir2        *print " drive, x user, y"
  506.     ifne    trs80
  507.     movea.l    #datmsg,a0    *print " Date:  "
  508.     jsr    print
  509.     jsr    loadtd        *put today's date in appropriate memory
  510.     jsr    display        *print today's date & time
  511.     endc
  512.     jsr    crlf
  513.     movea.l    #linmsg,a0
  514.     jsr    print
  515.     addq.b    #1,lincnt    *bump line count
  516.     bra    newlin        *start new line    and output the files
  517. *
  518. * Output the directory files we've matched.
  519. *
  520. entry:    subq    #1,count    *dock file count
  521.     beq    okprnt        *if count=0, last file so skip compare
  522. *
  523. * Compare each entry to    make sure that it isn't part of a multiple
  524. * extent file.    Go only    when we    have the last extent of    the file.
  525. *
  526.     jsr    ckabrt        *check for abort code from keyboard
  527.     movea.l    #nextt,a2
  528.     move.l    (a2),a3
  529.     move.l    (a3)+,a1
  530.     move.l    (a3),a0
  531.     jsr    compr        *does this entry match next one?
  532.     bne    okprnt        *no, print it
  533.     cmpi.b    #$20,stampon    *check for date stamps on
  534.     bne    nocarry
  535.     jsr    carry        *carry date stamp forward
  536. nocarry:
  537.     move.l    a3,nextt    *skip since highest extent comes last
  538.     bra    entry        *loop back for next lowest extent
  539. *
  540. * Valid    entry obtained - display it.
  541. *
  542. okprnt:    movea.l    #nextt,a2    *get order table pointer
  543.     move.l    (a2),a3        *get address
  544.     move.l    (a3)+,a1
  545.     move.l    a3,nextt    *save updated table pointer
  546.     moveq.l    #8,d2        *file name length
  547.     jsr    typeit        *type filename
  548.     move.b    #'.',d1        *period    after filename
  549.     jsr    type
  550.     jsr    savatrb        *save attribute flags
  551.     moveq.l    #3,d2        *display 3 characters of filetype
  552.     jsr    typeit
  553. *
  554. * Compute the size of the file and update our summary datum.
  555. *
  556.     move.b    (a1)+,extno    *get extent number
  557.     move.b    (a1)+,sectct    *get sector count of last extent
  558.     move.b    (a1)+,date1    *1st date byte
  559.     move.b    (a1)+,date2    *2nd date byte
  560.     move.b    (a1)+,hour    *hour
  561.     move.b    (a1)+,min    *munute
  562.     movea.l    #extno,a0
  563.     clr.l    d0
  564.     move.b    (a0),d0        *multiply number of
  565.     mulu    #16,d0        *extents by 16k
  566. *
  567.     ifne    truek
  568.     jsr    calcrec        *calculate number of records
  569.     divu    #8,d0        *convert to kbytes
  570.     move.l    d0,d1
  571.     swap    d1        *examine remainder
  572.     cmpi.w    #0,d1        *is it zero?
  573.     beq    fini        *yes...no leftover sectors
  574.     addq.w    #1,d0        *no....add another kbyte
  575.     endc
  576. *
  577.     ifeq    truek
  578.     movea.l    #blkmsk,a0
  579.     movea.l    #sectct,a1    *round last extent to block size
  580.     clr.l    d1
  581.     move.b    (a1),d1
  582.     add.b    (a0),d1
  583.     divu    #8,d1        *convert from sectors to k
  584.     add.b    d1,d0        *add to    total k
  585.     clr.l    d1
  586.     move.b    (a0),d1        *convert sec/blk to k/blk
  587.     divu    #8,d1
  588.     not.b    d1        *use to    finish rounding
  589.     and.b    d1,d0
  590.     endc
  591. *
  592. fini:    add.w    d0,totsiz    *add to    total used
  593.     addq.w    #1,totfil    *increment file    count
  594.     move.w    d0,d4        *save it in d4
  595. *
  596. * Output the size of the individual file.
  597. *
  598.     move.b    #space,d1    *begin with a space
  599.     jsr    type
  600.     jsr    decprt        *print file size
  601.     move.b    #'k',d1        *follow with 'k'
  602.     jsr    type
  603.     move.b    #space,d1    *and conclude with a space
  604.     jsr    type
  605. *.......................................................................
  606. * Output the number of records of the individual file
  607. *
  608. *    movea.l    #numrec,a0    *point to total records
  609. *    move.w    (a0),d4
  610. *    jsr    decprt        *print number of records
  611. *.......................................................................
  612. * Display attributes
  613. *
  614.     cmpi.b    #$80,rorw    *check RO/RW flag
  615.     bne    unpro
  616.     move.b    #'R',d1
  617.     bra    syschk
  618. unpro:    move.b    #space,d1
  619. syschk:    jsr    type
  620.     cmpi.b    #$80,sysdir    *check Sys/Dir flag
  621.     bne    unsys
  622.     move.b    #'S',d1
  623.     bra    arcchk
  624. unsys:    move.b    #space,d1
  625. arcchk:    jsr    type
  626.     cmpi.b    #$80,arciv    *check Archive flag
  627.     bne    unarc
  628.     move.b    #'A',d1
  629.     bra    alldone
  630. unarc:    move.b    #space,d1
  631. alldone:
  632.     jsr    type
  633.     move.b    #space,d1    *print a space
  634.     jsr    type
  635.     cmpi.b    #$20,stampon
  636.     bne    nodisp
  637.     jsr    display        *now the date and time
  638. *
  639. * One file output - test to see    if we have to output another one.
  640. *
  641. nodisp:    movea.l    #count,a2    *get current file counter and test it
  642.     cmpi.w    #0,(a2)
  643.     beq    prtotl        *if no more files, go to summary output
  644. *
  645. * At least one more file to output - can we put    it on the current line?
  646. *
  647.     subq.b    #1,colcnt
  648.     beq    nodis1
  649.     jsr    fence        *if room left, output column separator
  650. nodis1:    cmpi.b    #0,colcnt
  651.     bne    entry        *.. and    go output another file
  652. *
  653. * Current line full, start a new one.
  654. *
  655. newlin:    movea.l    #mnpl,a0
  656.     move.b    (a0),colcnt    *reset names per line counter
  657.     jsr    crlf        *space down to next line
  658.     bra    entry        *go back and output another file
  659. *
  660. * Print    d4 in decimal with leading zero    suppression
  661. *
  662. decprt:    move.b    #0,d5        *clear leading zero flag
  663.     movea.l    #supspc,a0    *get leading space suppression flag
  664.     move.b    (a0),d6
  665.     clr.l    d3        *print 1000's digit
  666.     move.w    d4,d3
  667.     divu    #1000,d3
  668.     move.l    d3,d4
  669.     jsr    digit
  670.     swap    d4
  671.     clr.l    d3        *print 100's digit
  672.     move.w    d4,d3
  673.     divu    #100,d3
  674.     move.l    d3,d4
  675.     jsr    digit
  676.     swap    d4
  677.     clr.l    d3        *print 10's digit
  678.     move.w    d4,d3
  679.     divu    #10,d3
  680.     move.l    d3,d4
  681.     jsr    digit
  682.     swap    d4
  683.     move.w    d4,d1        *print units digit
  684.     addi.b    #'0',d1
  685.     bra    type
  686. digit:    move.b    d3,d1
  687.     addi.b    #'0',d1
  688. digex:    cmpi.b    #'0',d1        *zero digit?
  689.     bne    dignz        *no, type it
  690.     cmpi.b    #0,d5        *leading zero?
  691.     bne    type        *print digit
  692.     cmpi.b    #0,d6        *is space suppression flag set?
  693.     bne    digsp        *no....print a leading space
  694.     rts            *yes...don't give leading spaces
  695. digsp:    bra    pspace        *leading zero...print space
  696. dignz:    move.b    #1,d5        *set leading zero flag so next zero
  697.     bra    type        *prints, and print digit
  698. *
  699. * Show total space and files used
  700. *
  701. prtotl:
  702.     move.b    #0,supspc    *suppress leading spaces in totals
  703.     movea.l    #totfil,a0    *how many files    did we match?
  704.     move.w    (a0),d0
  705.     cmpi.w    #0,d0
  706.     beq    nxtusr        *skip the summary if we    didn't find any
  707.     move.b    #1,fndflg    *set file found flag
  708.     jsr    crlf
  709.     jsr    prdir        *print "  drive, x user, y"
  710. nouser:    movea.l    #totms3,a0    *print " contains "
  711.     jsr    print
  712.     clr.l    d4
  713.     movea.l    #totsiz,a0    *print total k used by files matched
  714.     move.w    (a0),d4
  715.     jsr    decprt
  716.     movea.l    #totms4,a0    *print "k in "
  717.     jsr    print
  718.     clr.l    d4
  719.     movea.l    #totfil,a0    *recall    totfil
  720.     move.w    (a0),d4
  721.     jsr    decprt        *print number of files matched
  722.     movea.l    #totms5,a0    *print " files with "
  723.     jsr    print
  724.     jsr    prtfre        *output    free space remaining & " free"
  725. *
  726. * Directory for    one user area completed.  If all users option is
  727. * selected, then go do another directory on the    next user number
  728. * until    we exceed the maximum user # for the selected drive.
  729. *
  730. nxtusr:    nop
  731.     ifne    aopt        *if all    users option enabled
  732.     movea.l    #aopflg,a0    *if not    all users mode - skip next
  733.     cmpi.b    #0,(a0)
  734.     bne    goclz
  735.     jsr    ckabrt        *check for user    abort first
  736.     movea.l    #newusr,a1    *bump directory    user number
  737.     addq.b    #1,(a1)
  738.     cmpi.b    #usrmax,(a1)    *does next user    # exceed maximum?
  739.     blt    settbl        *continue if more user areas to    go
  740.     endc    *aopt
  741.     ifne    dopt and aopt    *if multi-disk option enabled
  742.     movea.l    #basusr,a0    *reset base user number    for the
  743.     move.b    (a0),newusr    *..next    directory search
  744.     endc            *balance dopt and aopt
  745. *
  746. * We've finished all of our outputting.  Flush the remainder of the
  747. * output buffer and close the file before going to exit routine.
  748. *
  749. goclz:    nop
  750. *
  751. * Directory for    all user areas completed.  If the multi-disk option
  752. * is enabled and selected, reset to the    base user area and repeat
  753. * the directory    for next drive on-line until we    either exceed the
  754. * drives on line, or the BDOS shuts us down with a select or bad
  755. * sector error,    which will be intercepted back to the exit module.
  756. *
  757. nxtdsk: movea.l    #fndflg,a0    *get file found flag
  758.     move.b    (a0),d0
  759.     move.b    #0,(a0)        *clear file found flag for next drive
  760.     cmpi.b    #0,d0
  761.     bne    ndsk        *continue if at least 1 file found
  762.     move.b    (a6),d0        *stash ascii directory drive
  763.     addi.b    #'A'-1,d0    *in no file message
  764.     move.b    d0,nofms2
  765.     jsr    crlf
  766.     movea.l    #nofms1,a0    *print "no file on ? - "
  767.     jsr    print
  768.     jsr    prtfre        *tag with free message
  769. ndsk:    nop
  770.     ifne    dopt        *if multi-disk option enabled
  771.     movea.l    #dopflg,a0    *if multi-disk not selected - skip next
  772.     cmpi.b    #0,(a0)
  773.     bne    nprt
  774.     jsr    ckabrt        *check for user    abort first
  775.     addq.b    #1,(a6)        *bump directory    fcb drive code
  776.     cmpi.b    #stskip,(a6)    *skip if start skip
  777.     bne    next1
  778.     move.b    #skipto,(a6)    *if stskip then skipto
  779. next1:    cmpi.b    #drvmax,(a6)    *does next disk    exceed maximum?
  780.     ble    noopt        *search    next disk if not
  781.     endc            *balance dopt
  782. nprt:    nop            *if no printer, fall through to exit
  783.     ifne    popt        *now, check if printer is in use
  784.     movea.l    #popflg,a0
  785.     cmpi.b    #0,(a0)        *printer active?
  786.     bne    exit        *no, just exit...
  787.     move.w    #listout,d0
  788.     move.b    #cr,d1        *print a carriage return
  789.     trap    #bdos
  790.     move.b    #lf,d1        *and a line feed
  791.     trap    #bdos
  792.     endc    *popt
  793.     bra    exit        *all done - exit to ccp
  794. *
  795. * Print "directory for....
  796. *
  797. prdir:    movea.l    #linmsg,a0
  798.     jsr    print
  799.     jsr    crlf
  800.     jsr    margin        *set the margin
  801. prdir2:    movea.l    #totms1,a0    *print  " Drive "
  802.     jsr    print
  803.     movea.l    a6,a0        *point to fcb
  804.     move.b    (a0),d1
  805.     add.b    #'A'-1,d1
  806.     jsr    type        *output    the drive code
  807.     movea.l    #totms2,a0    *print ", user "
  808.     jsr    print
  809.     jsr    typusr        *output    the user number
  810. prdir1:    rts
  811. *
  812. * Print    the user number    of the directory in decimal
  813. *
  814. typusr:    movea.l    #newusr,a0
  815.     move.b    (a0),d2
  816.     cmpi.b    #10,d2        *if user no. > 9 print leading 1
  817.     blt    dux
  818.     move.b    #'1',d1
  819.     jsr    type
  820.     subi.b    #10,d2        *extract low digit of user no.
  821. dux:    addi.b    #'0',d2        *make it ascii
  822.     move.b    d2,d1        *and display it
  823.     bra    type
  824. *
  825. * Force    new line on video and check for    page pause
  826. *
  827. crlf:    move.b    #cr,d1        *send cr
  828.     jsr    type
  829.     move.b    #lf,d1        *send lf
  830.     bra    type        *exit to caller    from type
  831. *
  832. * Separate the directory output    on a line with two spaces,
  833. * the delimiter, followed by two more spaces.
  834. *
  835. fence:    jsr    pspace
  836.     jsr    pspace
  837.     move.b    #delim,d1    *fence character
  838.     jsr    type        *print it, fall    into space
  839.     move.b    #space,d1
  840.     jsr    type
  841. pspace:    move.b    #space,d1    *fall through to type
  842. *
  843. * Output character in d1 to console, and optionally to printer.
  844. *
  845. type:
  846.     jsr    type1        *send it to console
  847.     andi.b    #$7f,d1        *strip parity bit on character
  848. *
  849. * Test file output mode and skip to page pause test if not active.
  850. *
  851.     ifne    popt        *if printer option
  852.     movea.l    #popflg,a3    *test printer flag
  853.     cmpi.b    #0,(a3)
  854.     bne    cheklf
  855.     move.w    #listout,d0    *setup list output call
  856.     trap    #bdos        *print character if flag true
  857.     endc
  858. cheklf:    cmpi.b    #lf,d1        *do we have a lf?
  859.     bne    typret        *exit if not
  860.     ifne    nopt
  861.     movea.l    #nopflg,a3    *is the    page pause function disabled?
  862.     cmpi.b    #0,(a3)
  863.     beq    typret        *exit if so
  864.     endc
  865.     movea.l    #lincnt,a3    *get line count
  866.     move.b    (a3),d0
  867.     addq.b    #1,d0        *bump it
  868.     cmpi.b    #lps,d0        *are we    at the end of the screen?
  869.     blt    noteos        *skip if not
  870.     move.l    #eosmsg,d1    *else, display pause message
  871.     move.w    #pstring,d0    *..without checking for    lfs
  872.     trap    #bdos
  873.     jsr    cinput        *wait for character
  874.     cmpi.b    #break,d0
  875.     beq    exit        *abort on ^C
  876.     move.b    #0,d0        *reset line count
  877. noteos:    move.b    d0,(a3)        *save new line count
  878. typret:    rts            *exit from type
  879. *
  880. * Output character
  881. *
  882. type1:
  883.     move.w    #wrchr,d0
  884.     trap    #bdos        *call conout via the bdos
  885.     rts
  886. *
  887. * Print    a string at a1 of length d2
  888. *
  889. typeit:    move.b    (a1)+,d1
  890.     jsr    type
  891.     subq    #1,d2
  892.     bne    typeit
  893.     rts
  894. *
  895. * Print    string terminated with '$' character by character.
  896. *
  897. print:    move.b    (a0)+,d1    *get a character
  898.     cmpi.b    #'$',d1        *is it the end of the string?
  899.     bne    print1
  900.     rts            *yes...return
  901. print1:    and.b    #$7f,d1        *no....strip parity bit
  902.     jsr    type        *display it
  903.     bra    print        *and loop back for another character
  904. *
  905. * Fetch    character from console (without    echo)
  906. *
  907. cinput:    move.w    #$ff,d1
  908.     move.w    #dirio,d0
  909.     trap    #bdos
  910.     andi.b    #$7f,d0
  911.     rts
  912. *
  913. * Check    for a ^C or ^S entered from the    keyboard.  Jump    to exit
  914. *  if ^C...pause on ^S.
  915. *
  916. ckabrt:    move.w    #$fe,d1        *check status of keyboard
  917.     move.w    #dirio,d0
  918.     trap    #bdos
  919.     cmpi.b    #0,d0        *any key pressed?
  920.     bne    get1
  921.     rts            *no, return to caller
  922. get1:    jsr    cinput        *get character
  923.     cmpi.b    #break,d0    *is it ^C?
  924.     beq    exit        *if ^C then quit
  925.     cmpi.b    #xoff,d0    *is it ^S?
  926.     beq    get2        *yes, wait for another character
  927.     rts            *no, return to caller
  928. get2:    jsr    cinput        
  929.     cmpi.b    #break,d0    *might be ^C
  930.     beq    exit        *exit if ^C else fall thru & continue
  931.     rts
  932. *
  933. * For file output mode,    return to old user area    and set    dma for
  934. * the file output buffer.
  935. *
  936. setfop:    nop
  937.     ifne    uopt or    aopt
  938.     movea.l    #oldusr,a0    *get user number at startup
  939.     clr.l    d1
  940.     move.b    (a0),d1
  941.     move.w    #curusr,d0
  942.     trap    #bdos        *reset the old user number
  943.     endc
  944.     rts
  945. *
  946. * Move disk buffer dma to default buffer for directory search operations
  947. * and bdos media change routines.
  948. *
  949. setsrc: 
  950.     move.l    a5,d1
  951.     move.w    #setdma,d0
  952.     trap    #bdos
  953.     clr.l    d1
  954.     rts
  955. *
  956. * Print    the amount of free space remaining on the selected drive.
  957. *
  958. prtfre: clr.l    d4
  959.     movea.l    #freeby,a0    *get space left
  960.     move.w    (a0),d4
  961.     jsr    decprt        *print k free
  962.     movea.l    #totms6,a0    *print " free"
  963.     bra    print
  964. *
  965. * Compare two consecutive files for possible multiple extents
  966. *
  967. compr:
  968.     move.l    #11,d2        *compare fn, ft
  969. cmplp:    move.b    (a0)+,d0
  970.     andi.b    #$7f,d0    
  971.     move.b    (a1)+,d1    
  972.     andi.b    #$7f,d1    
  973.     cmp.b    d1,d0
  974.     beq    domor
  975.     rts
  976. domor:    subq    #1,d2        
  977.     bne    cmplp
  978.     rts
  979. *
  980. * Swap entries in the order table
  981. *
  982. swap:    
  983.     movea.l    #order-4,a2    *table base
  984.     mulu    #4,d0        *index x 4
  985.     move.l    d0,a0
  986.     adda.l    a2,a0        *+ base
  987.     mulu    #4,d1        *index x 4
  988.     move.l    d1,a1
  989.     adda.l    a2,a1        *+ base
  990.     move.l    (a0),d0
  991.     move.l    (a1),d1
  992.     move.l    d0,(a1)
  993.     move.l    d1,(a0)
  994.     rts
  995. *
  996. * Compare routine - modified for filetype sort
  997. *
  998. compare:
  999.     movea.l    #order-4,a2    *table base
  1000.     mulu    #4,d0        *index x 4
  1001.     move.l    d0,a3
  1002.     adda.l    a2,a3        *+ base
  1003.     move.l    (a3),a0
  1004.     mulu    #4,d1        *index x 4
  1005.     move.l    d1,a4
  1006.     adda.l    a2,a4        *+ base
  1007.     move.l    (a4),a1
  1008. *
  1009. * Compare by filename, filetype, extent - in that order
  1010. *
  1011. cmpfnft:
  1012.     move.l    #12,d2        *compare fn, ft, ex
  1013. cmplpe:    move.b    (a0)+,d0
  1014.     andi.b    #$7f,d0    
  1015.     move.b    (a1)+,d1    
  1016.     andi.b    #$7f,d1    
  1017.     cmp.b    d1,d0
  1018.     beq    domore
  1019.     rts
  1020. domore:    subq    #1,d2        
  1021.     bne    cmplpe
  1022.     rts
  1023. *
  1024. * Print a short help message
  1025. *
  1026. help:    move.l    #hlpmes,d1
  1027.     move.w    #pstring,d0
  1028.     trap    #bdos
  1029.     bra    exit
  1030. *
  1031. * Error    exit
  1032. *
  1033. erxit:    jsr    print        *print first part of message
  1034.     movea.l    #errms1,a0    *print " Error"
  1035.     jsr    print
  1036.     jsr    crlf        *space down
  1037. *
  1038. * Exit - all done
  1039. *
  1040. exit:    move.w    #const,d0    *check console status
  1041.     trap    #bdos
  1042.     cmpi.b    #0,d0        *char waiting?
  1043.     beq    exit1        *no...return to CP/M
  1044.     move.w    #rdchr,d0    *otherwise...
  1045.     trap    #bdos        *gobble    up char
  1046. exit1:    move.w    #boot,d0    *..and return to CP/M
  1047.     trap    #bdos
  1048. *
  1049. * Recovery point from intercepted bdos select and bad sector errors.
  1050. *
  1051.     ifne    dopt
  1052. dskerr:    bra    exit        *..and exit back to ccp
  1053.     endc
  1054. *
  1055. * calculate number of records in file
  1056. *
  1057. calcrec:
  1058.     mulu    #8,d0        *convert extent count to records
  1059.     clr.l    d1
  1060.     movea.l    #sectct,a0    *now add the # of records
  1061.     move.b    (a0),d1        *in the final extent
  1062.     add.w    d1,d0        *d0 now contains # of records
  1063.     move.w    d0,numrec    *save it in numrec and
  1064.     rts            *...return
  1065. *
  1066. *  Clear all data registers
  1067. *
  1068. clear:
  1069.     clr.l    d0
  1070.     clr.l    d1
  1071.     clr.l    d2
  1072.     clr.l    d3
  1073.     clr.l    d4
  1074.     clr.l    d5
  1075.     clr.l    d6
  1076.     clr.l    d7
  1077.     rts
  1078. *
  1079. * Indent left margin
  1080. *
  1081. margin:
  1082.     clr.l    d2
  1083.     movea.l    #indent,a0
  1084.     move.b    (a0),d2
  1085. repeat:    jsr    pspace
  1086.     subq    #1,d2
  1087.     bge    repeat
  1088.     rts
  1089. *
  1090. * Move d2 bytes from a1 to a0
  1091. *
  1092. movmem:
  1093.     move.b    (a1)+,(a0)+
  1094.     subq    #1,d2
  1095.     bne    movmem
  1096.     rts
  1097. *
  1098. * Save attribute flags
  1099. *
  1100. savatrb:
  1101.     movea.l    a1,a2
  1102.     move.b    (a2)+,d0    *check RO/RW flag
  1103.     andi.b    #$80,d0
  1104.     move.b    d0,rorw        *save it in rorw
  1105.     move.b    (a2)+,d0    *check Sys/Dir flag
  1106.     andi.b    #$80,d0
  1107.     move.b    d0,sysdir    *save it in sysdir
  1108.     move.b    (a2)+,d0    *check Archive flag
  1109.     andi.b    #$80,d0
  1110.     move.b    d0,arciv    *save it in arciv
  1111.     rts
  1112. *
  1113. * Check for drivespec = logged drive and set fcb if it is
  1114. *
  1115. setdflt:
  1116.     cmpi.b    #0,(a6)        *is it the default drive?
  1117.     bne    morchk        *no....must check further
  1118.     rts            *yes...return
  1119. morchk:    movea.l    #olddsk,a4    *point to currently logged drive
  1120.     move.b    (a4),d0        *put it in d0
  1121.     addq.b    #1,d0        *make it absolute
  1122.     cmp.b    (a6),d0        *is it the same as the specified drive?
  1123.     beq    mkdflt        *yes...make the fcb contain a zero
  1124.     rts            *no....return
  1125. mkdflt:    move.b    #0,(a6)        *first byte in fcb = 0
  1126.     rts
  1127. *
  1128. *#######################################################################
  1129. *                 Special DMA Parsing Subroutines
  1130. *#######################################################################
  1131. *
  1132. * Check dma for user area specified as part of drive specification
  1133. *
  1134. parse:
  1135.     movea.l    a5,a4        *point to dma
  1136.     move.b    (a4),d7        *get length of command string
  1137.     cmpi.b    #0,d7        *no command tail?
  1138.     beq    finish
  1139.     move.b    #1,d5
  1140. char1:    adda    #1,a4        *point to next character
  1141.     cmpi.b    #space,(a4)    *is it a space?
  1142.     bne    gotch1        *no....mark its position
  1143.     addq    #1,d5        *yes...bump position marker
  1144.     subq    #1,d7        *1 less character remaining
  1145.     bne    char1        *check next character
  1146.     rts            *all done if no more characters
  1147. gotch1:    cmpi.b    #'[',(a4)    *is it a '['?
  1148.     beq    finish        *all done, no drive specified
  1149.     subq    #1,d7        *dock characters remaining
  1150.     beq    finish        *all done if no more
  1151.     add.b    d5,d6        *bump marker to next position
  1152. colon:    adda    #1,a4        *now look for a ':'
  1153.     cmpi.b    #':',(a4)    *is it a ':'?
  1154.     beq    gotcln        *yes...mark its position
  1155.     cmpi.b    #'[',(a4)    *is it a '['?
  1156.     beq    finish        *all done, no drive specified
  1157.     addq    #1,d6        *no...bump position marker
  1158.     subq    #1,d7        *1 less character remaining
  1159.     beq    finish        *all done if no more characters
  1160.     bra    colon        *check next character
  1161. gotcln:    addq.b    #1,d6        *increment marker one more time
  1162.     sub.b    d5,d6        *compute their difference
  1163.     cmpi.b    #1,d6        *is it 1?
  1164.     beq    finish        *yes...no rearrangement necessary
  1165. try2:    cmpi.b    #2,d6        *is it 2?
  1166.     beq    onedig        *yes...it's a one digit user
  1167.     cmpi.b    #3,d6        *is it 3?
  1168.     beq    twodig        *yes...it's a two digit user
  1169.     move.l    #synerr,d1    *otherwise, we have an error
  1170.     move.w    #pstring,d0    *say so and quit
  1171.     trap    #bdos
  1172.     bra    help
  1173. onedig:    suba    #2,a4        *back up to drive designator
  1174.     move.b    (a4)+,d0    *get drive designator
  1175.     move.b    d0,drive    *save it in drive
  1176.     move.b    (a4)+,d0    *get user number
  1177.     move.b    d0,tail+2    *save it
  1178.     move.b    #']',tail+3    *append a ']'
  1179.     bra    fixfcb        *go fix up the fcb
  1180. twodig:    suba    #3,a4        *back up to drive designator
  1181.     move.b    (a4)+,d0    *get drive designator
  1182.     andi.b    #upmask,d0    *make it upper case
  1183.     move.b    d0,drive    *save it in drive
  1184.     move.b    (a4)+,d0    *get first digit of user number
  1185.     move.b    d0,tail+2    *save it
  1186.     move.b    (a4)+,d0    *get second digit of user number
  1187.     move.b    d0,tail+3    *save it
  1188.     move.b    #']',tail+4    *append a ']'
  1189. fixfcb:    subq    #1,d7        *dock characters remaining
  1190.     beq    stuff        *no file name...go stuff the fcb
  1191.     movea.l    #fname,a3    *point to file name storage buffer
  1192.     move.l    #8,d2        *8 characters max
  1193. getnam:    adda    #1,a4        *point to next character
  1194.     move.b    (a4),d0        *get it
  1195.     cmpi.b    #'[',d0        *is it a '['?
  1196.     beq    stuff        *yes...we have the whole file name
  1197.     cmpi.b    #'.',d0        *is it a '.'?
  1198.     beq    gettyp        *yes...file type follows
  1199.     move.b    d0,(a3)+    *save the character
  1200.     subq    #1,d2        *dock file name char counter
  1201.     beq    getdot        *we have all 8 characters...strip '.'
  1202.     subq    #1,d7        *dock characters remaining
  1203.     beq    stuff        *out of characters...go stuff the fcb
  1204.     bra    getnam        *go back for another character
  1205. getdot:    subq    #1,d7        *dock characters remaining
  1206.     beq    stuff        *no more left...go stuff the fcb
  1207.     adda    #1,a4        *otherwise point to next character
  1208.     move.b    (a4),d0        *get it
  1209.     cmpi.b    #'[',d0        *is it a '['?
  1210.     beq    stuff        *yes...go stuff the fcb
  1211.     cmpi.b    #'.',d0        *is it a '.'?
  1212.     beq    gettyp        *yes...skip over it
  1213.     move.l    #synerr,d1    *no....this is incorrect
  1214.     move.w    #pstring,d0    *say so and quit
  1215.     trap    #bdos
  1216.     bra    help
  1217. gettyp:    subq    #1,d7        *dock characters remaining
  1218.     beq    stuff        *no type given...go stuff the fcb
  1219.     movea.l #ftype,a3    *point to file type buffer
  1220.     move.l    #3,d2        *3 characters max
  1221. gettyp1:adda    #1,a4        *point to next character
  1222.     move.b    (a4),d0        *get it
  1223.     cmpi.b    #'[',d0        *is it a '['?
  1224.     beq    stuff        *yes...we have the whole file type
  1225.     move.b    d0,(a3)+    *save the character
  1226.     subq    #1,d2        *dock file type char counter
  1227.     beq    stuff        *we have all 3 chars...go stuff fcb
  1228.     subq    #1,d7        *dock characters remaining
  1229.     beq    stuff        *no more left...go stuff fcb
  1230.     bra    gettyp1        *go back for another character
  1231. stuff:    movea.l    #fname,a3    *parse file name and make
  1232.     move.l    #8,d2        *upper case...also, expand '*'
  1233.     jsr    wldfil        *to a string of ?'s
  1234.     movea.l    #ftype,a3    *parse file type and make
  1235.     move.l    #3,d2        *upper case...also, expand '*'
  1236.     jsr    wldfil        *to a string of ?'s
  1237.     movea.l    #drive,a1    *get drive designator
  1238.     subi.b    #'A'-1,(a1)    *make it a number
  1239.     move.l    #12,d2        *finally, copy all to the fcb
  1240.     movea.l    a6,a0        *point to fcb
  1241.     jsr    movmem        *and do the copy
  1242. fixdma:    movea.l    a5,a0        *now see if we have any options
  1243.     move.b    (a0),d7        *get character count
  1244.     move.b    d7,d6        *save it in d6
  1245. lbrak:    addq    #1,a0        *point to next character
  1246.     cmpi.b    #'[',(a0)    *is it the delimiter?
  1247.     beq    gotlb        *yes...exit this loop
  1248.     subq    #1,d7        *dock counter
  1249.     beq    nolb        *no options specified
  1250.     bra    lbrak        *go back for another character
  1251. gotlb:    subq    #1,d7        *dock counter
  1252.     beq    nolb        *funny case...but add tail anyhow
  1253. rbrak:    adda    #1,a0        *point to next character
  1254.     cmpi.b    #']',(a0)    *is it ']'?
  1255.     beq    adtail        *yes...go add the tail
  1256.     subq    #1,d7        *no....dock the counter
  1257.     beq    adtail        *out of chars...add the tail
  1258.     bra    rbrak        *go back for another character
  1259. adtail:    movea.l    #tail+1,a1    *point to user spec without '['
  1260.     move.l    #5,d2
  1261.     jsr    movmem        *and copy tail to dma
  1262.     addi.b    #4,d6        *adjust for the 4 characters appended
  1263.     move.b    d6,(a5)        *copy adjusted character count to dma
  1264.     rts
  1265. nolb:    movea.l    #tail,a1    *point to user spec with '['
  1266.     move.l    #6,d2
  1267.     jsr    movmem        *and copy tail to dma
  1268.     addi.b    #5,d6        *adjust for the 5 characters appended
  1269.     move.b    d6,(a5)        *copy adjusted character count to dma
  1270. finish:    rts
  1271. *
  1272. * Parse file name or type, make upper case and expand * to trailing ?'s
  1273. *
  1274. wldfil:    move.b    (a3),d0
  1275.     cmpi.b    #'*',d0
  1276.     beq    qmfill
  1277.     subq    #1,d2
  1278.     bne    upper
  1279.     rts
  1280. upper:    cmpi.b    #'a',d0
  1281.     blt    wldnxt
  1282.     andi.b    #upmask,d0
  1283.     move.b    d0,(a3)
  1284. wldnxt:    adda    #1,a3
  1285.     bra    wldfil
  1286. qmfill:    move.b    #'?',(a3)+
  1287.     subq    #1,d2
  1288.     bne    qmfill
  1289.     rts
  1290. *
  1291. *#######################################################################
  1292. *                Time and Date Stamping Subroutines
  1293. *#######################################################################
  1294. *
  1295. * Carry date/time stamp forward for multiple extent file
  1296. *
  1297. carry:
  1298.     adda    #2,a1        *make a1 point to date stamp
  1299.     adda    #2,a0        *make a0 point to blank date stamp
  1300.     move.l    #4,d2        *copy the date stamp
  1301.     jsr    movmem        *from a1 to a0
  1302.     rts
  1303. *
  1304. * Check for time and date stamps
  1305. *
  1306. chkstmp:nop
  1307.     ifne    trs80
  1308.     movea.l    #trkoff,a0    *determine the directory track
  1309.     movea.l    #trakno,a1    *number and put it in #trakno
  1310.     clr.l    d3
  1311.     move.w    (a0),d3
  1312.     move.l    d3,(a1)
  1313.     jsr    strack        *position head at the start
  1314.     jsr    ssector        *of the directory track
  1315.     jsr    dmaset        *set dma address
  1316.     jsr    rsector        *and read the first sector
  1317.     cmpi.b    #1,d0        *any errors?
  1318.     bne    readok
  1319.     movea.l    #direrr,a0    *say so and quit on error
  1320.     bra    erxit
  1321. readok:    movea.l    #biosdma,a0    *check for stamping marker
  1322.     cmpi.b    #marker,96(a0)    *is directory properly formatted?
  1323.     bne    noton        *if not, date stamping not enabled
  1324.     move.b    #$20,stampon
  1325.     rts
  1326.     endc
  1327. noton:    move.b    #0,stampon
  1328.     rts
  1329. *
  1330. *  Set dma address for bios calls
  1331. *
  1332. dmaset:
  1333.     move.w    #calbios,d0
  1334.     move.l    #dmabpb,d1
  1335.     trap    #bdos
  1336.     rts
  1337. dmabpb:    dc.w    12        *set dma address bios parameter block
  1338.     dc.l    biosdma        *use special dma for bios calls
  1339.     dc.l    0
  1340. *
  1341. *  Read a sector
  1342. *
  1343. rsector:
  1344.     move.w    #calbios,d0
  1345.     move.l    #rsbpb,d1
  1346.     trap    #bdos
  1347.     rts
  1348. rsbpb:    dc.w    13        *read sector bios parameter block
  1349.     dc.l    0
  1350.     dc.l    0
  1351. *
  1352. *  Set track number
  1353. *
  1354. strack:
  1355.     move.w    #calbios,d0
  1356.     move.l    #stbpb,d1
  1357.     trap    #bdos
  1358.     rts
  1359. stbpb:    dc.w    10        *set track bios parameter block
  1360. trakno:    dc.l    1        *default track = 1
  1361.     dc.l    0
  1362. *
  1363. *  Set sector number
  1364. *
  1365. ssector:
  1366.     move.w    #calbios,d0
  1367.     move.l    #ssbpb,d1
  1368.     trap    #bdos
  1369.     rts
  1370. ssbpb:    dc.w    11        *set sector bios parameter block
  1371. sectno:    dc.l    0        *default sector = 0
  1372.     dc.l    0
  1373. *
  1374. *  Display date and time on the console
  1375. *
  1376. display:
  1377.     clr.l    d6        *put number of days since 1/1/78
  1378.     clr.l    d7        *into register d7
  1379.     movea.l    #date1,a1    *point to date
  1380.     move.b    (a1)+,d6    *low order byte  -> d6
  1381.     move.b    (a1),d7        *high order byte -> d7
  1382.     mulu    #$100,d7    *multiply by $100
  1383.     add.w    d6,d7        *d7 now contains 16-bit # of days
  1384.     cmpi.w    #0,d7        *is the file time/date stamped?
  1385.     beq    nostamp        *no...then display blanks
  1386.     jsr    year        *determine year
  1387.     jsr    month        *determine month
  1388.     moveq.l    #10,d3        *make base 10 decimal
  1389.     move.l    d4,d0        *get the month
  1390.     jsr    prtdec0        *make it decimal and print it
  1391.     move.b    #'/',d1        *insert a '/'
  1392.     jsr    type
  1393.     move.l    d5,d0        *get the day
  1394.     jsr    prtdec        *make it decimal and print it
  1395.     move.b    #'/',d1        *insert a '/'
  1396.     jsr    type
  1397.     move.l    d6,d0        *get the year
  1398.     jsr    prtdec        *make it decimal and print it
  1399.     move.b    #space,d1    *insert a space
  1400.     jsr    type
  1401.     moveq.l    #$10,d3        *make base 10 hexadecimal
  1402.     movea.l    #hour,a0    *get the hour
  1403.     move.b    (a0),d0
  1404.     jsr    prtdec0        *make it decimal and print it
  1405.     move.b    #':',d1        *insert a ':'
  1406.     jsr    type
  1407.     movea.l    #min,a0        *get the minutes
  1408.     move.b    (a0),d0
  1409.     jsr    prtdec        *make it decimal and print it
  1410.     rts
  1411. nostamp:
  1412.     movea.l    #blnkdt,a0    *print blanks if not time/date stamped
  1413.     jsr    print
  1414.     rts
  1415. *
  1416. *  Convert from binary to hexadecimal
  1417. *
  1418. binhex:
  1419.     clr.l    d2
  1420.     divu    #$10,d1
  1421.     move.w    d1,d2
  1422.     mulu    #10,d2
  1423.     clr.w    d1
  1424.     swap    d1
  1425.     add.w    d2,d1
  1426.     rts
  1427. *
  1428. *  Convert from hexadecimal to binary
  1429. *
  1430. hexbin:
  1431.     clr.l    d2
  1432.     divu    #10,d1
  1433.     move.w    d1,d2
  1434.     mulu    #$10,d2
  1435.     clr.w    d1
  1436.     swap    d1
  1437.     add.w    d2,d1
  1438.     rts
  1439. *
  1440. * Move today's date from tdate to date1
  1441. *
  1442. loadtd:
  1443.     move.l    #4,d2
  1444.     movea.l    #tdate,a1
  1445.     movea.l    #date1,a0
  1446.     jsr    movmem
  1447.     rts
  1448. *
  1449. *  Determine month
  1450. *
  1451. month:
  1452.     moveq.l    #1,d4        *initialize month register
  1453.     move.l    d7,d0        *get number of day in current year
  1454.     move.l    d0,d1
  1455.     move.l    #feb,a2        *point to number of days in February
  1456.     add.w    d5,(a2)        *adjust for leap year
  1457.     move.l    #jan,a2        *point to number of days in January
  1458. findmo:    sub.w    (a2)+,d1
  1459.     ble    donem        *quit if this is the month
  1460.     addq    #1,d4        *otherwise...increment month number
  1461.     move.w    d1,d0
  1462.     bra    findmo        *and repeat until month is determined
  1463. donem:    move.w    d0,d5        *save day of current month in d5
  1464.     rts
  1465. *
  1466. *  Convert to decimal and display
  1467. *
  1468. prtdec:
  1469.     divu    d3,d0        *divide by base
  1470.     move.w    d0,d1        *put tens digit in d1
  1471.     swap    d0
  1472.     move.w    d0,d2        *put units digit in d2
  1473.     addi.b    #48,d1        *make tens digit ascii
  1474.     jsr    type        *and display it
  1475.     move.w    d2,d1        *get units digit
  1476.     addi.b    #48,d1        *make it ascii
  1477.     jsr    type        *and display it
  1478.     rts
  1479. *
  1480. *  Convert to decimal and display, substituting space for
  1481. *  leading zero
  1482. *
  1483. prtdec0:
  1484.     divu    d3,d0        *divide by base
  1485.     move.w    d0,d1        *put tens digit in d1
  1486.     swap    d0
  1487.     move.w    d0,d2        *put units digit in d2
  1488.     cmpi.b    #0,d1        *is the tens digit zero?
  1489.     beq    prtspc        *yes...print a space
  1490.     addi.b    #48,d1        *no....make tens digit ascii
  1491.     bra    cont
  1492. prtspc:    move.b    #space,d1
  1493. cont:    jsr    type        *and display it
  1494.     move.w    d2,d1        *get units digit
  1495.     addi.b    #48,d1        *make it ascii
  1496.     jsr    type        *and display it
  1497.     rts
  1498. *
  1499. * Get today's date and time by reading the number of days since
  1500. * January 1, 1978 from the CP/M Plus System Control Block
  1501. *
  1502. today:
  1503.     move.l    #$daf4,d1    *Z80 address of low order date byte
  1504.     jsr    readz80        *read it into d1
  1505.     movea.l    #tdate,a3
  1506.     move.b    d1,(a3)+    *save it in tdate
  1507.     move.l    #$daf5,d1    *Z80 address of high order date byte
  1508.     jsr    readz80        *read it into d1
  1509.     move.b    d1,(a3)+    *save it in tdate+1
  1510.     move.l    #$daf6,d1    *Z80 address of hour
  1511.     jsr    readz80        *read it into d1
  1512.     move.b    d1,(a3)+    *save it in tdate+2
  1513.     move.l    #$daf7,d1    *Z80 address of minutes
  1514.     jsr    readz80        *read it into d1
  1515.     move.b    d1,(a3)        *save it in tdate+3
  1516.     clr.l    d0        *clean up registers
  1517.     clr.l    d1
  1518.     clr.l    a0
  1519.     clr.l    a1
  1520.     rts
  1521. *
  1522. *  Read a byte of Z80 memory
  1523. *
  1524. readz80:
  1525.     swap    d1        *put Z80 address in upper word
  1526.     move.w    #z80r,d0    *and call special function
  1527.     trap    #bios        *through the BIOS
  1528.     rts
  1529. *
  1530. *  Determine year
  1531. *
  1532. year:
  1533.     clr.l    d1
  1534.     clr.l    d5
  1535.     moveq.l    #78,d6        *base year is 1978
  1536.     move.l    d7,d0        *get number of days since 1/1/78
  1537.     divu    #1461,d0    *home in on 4-year interval (1461 days)
  1538.     move.w    d0,d1
  1539.     mulu    #4,d1
  1540.     add.w    d1,d6        *adjust year for 4-year interval base
  1541. *
  1542.     swap    d0        *now examine the remainder
  1543.     move.w    d0,d1
  1544.     cmpi.w    #0,d1        *see if it's December 31
  1545.     bne    not1231        *if not...continue
  1546.     move.w    #365,d0        *if so...adjust
  1547.     subq    #1,d6
  1548.     bra    doney
  1549. *
  1550. not1231:subi    #365,d1        *subtract 365 days
  1551.     ble    doney        *negative or zero => this is the year
  1552.     addq    #1,d6        *otherwise add 1 to year
  1553.     move.w    d1,d0        *save remaining number of days
  1554. *
  1555.     subi    #365,d1        *subtract another 365 days
  1556.     ble    doney        *negative or zero => this is the year
  1557.     addq    #1,d6        *otherwise add 1 to year
  1558.     move.w    d1,d0        *save remaining number of days
  1559. *
  1560.     move.b    #1,d5        *set the leap-year flag
  1561.     subi    #366,d1        *subtract 366 days (leap year)
  1562.     ble    doney        *negative or zero => this is the year
  1563.     addq    #1,d6        *otherwise add 1 to year
  1564.     clr.l    d5        *reset the leap-year flag
  1565.     move.w    d1,d0        *save remaining number of days
  1566. *
  1567. doney:    move.w    d0,d7        *save day of year in d7
  1568.     rts
  1569. *#######################################################################
  1570. *
  1571. * End of program code
  1572. *
  1573. * Initialized data area
  1574. *
  1575.     even
  1576. jan:    dc.w    31
  1577. feb:    dc.w    28
  1578. mar:    dc.w    31
  1579. apr:    dc.w    30
  1580. may:    dc.w    31
  1581. jun:    dc.w    30
  1582. jul:    dc.w    31
  1583. aug:    dc.w    31
  1584. sep:    dc.w    30
  1585. oct:    dc.w    31
  1586. nov:    dc.w    30
  1587. dec:    dc.w    31
  1588. blnkdt:    dc.b    '              $'
  1589. direrr:    dc.b    cr,lf,'Directory Read$'
  1590. dremsg:    dc.b    cr,lf,'Drive Specification$'
  1591. eosmsg: dc.b    '    Press ANY KEY to continue',cr,'$'
  1592. errms1: dc.b    space
  1593. errms2:    dc.b    'Error$'
  1594. nofms1: dc.b    'No Matching Files on Drive '
  1595.     even
  1596. nofms2: dc.b    ' :  $'
  1597. datmsg:    dc.b    tab,tab,tab,tab,'  Date:  $'
  1598. dirms1:    dc.b    'Directory for $'
  1599. linmsg:    dc.b    '----------------------------------------'
  1600.     dc.b    '---------------------------------------$'
  1601. totms1:    dc.b    'Drive $'
  1602. totms2:    dc.b    ': User $'
  1603. totms3:    dc.b    ' contains $'
  1604. totms4: dc.b    'k in $'
  1605. totms5:    dc.b    ' files with $'
  1606. totms6: dc.b    'k free',cr,lf,lf,'$'
  1607. usrmsg: dc.b    cr,lf,'User Number$'
  1608. ro:    dc.b    '  RO'
  1609. rw:    dc.b    '  RW'
  1610. sys:    dc.b    ' Sys'
  1611. dir:    dc.b    ' Dir'
  1612. arc:    dc.b    ' Arc'
  1613. nonarc:    dc.b    '    '
  1614.     even
  1615. drive:    dc.b    0        *drive
  1616. fname:    dc.b    '        '    *file name
  1617. ftype:    dc.b    '   '        *file type
  1618. tail:    dc.b    '[U',0,0,0,0    *dma tail (for user number)
  1619. synerr:    dc.b    cr,lf,lf,' Syntax Error ','$'
  1620. *
  1621. * Option field lookup table.
  1622. * Note that you    can force any of these options as a default by
  1623. * changing the letter for the option into a zero (assuming that
  1624. * its enabling equate is true).     Each option that you hard-wire    in
  1625. * this manner will no longer be    recognized as a    command    line option,
  1626. * and if you redundantly key it in, SD will flag it as unrecognized.
  1627. *
  1628. otbl    equ    *        *mark start of option table
  1629.     ifne    aopt        *all users-option flag
  1630. aopflg:    dc.b    'A'
  1631.     endc
  1632.     ifne    dopt        *multi-disk-option flag
  1633. dopflg:    dc.b    'D' 
  1634.     endc
  1635.     ifne    nopt        *no page-pause option flag
  1636. nopflg:    dc.b    'N'
  1637.     endc
  1638.     ifne    ropt        *unarchived file option    flag
  1639. ropflg:    dc.b    'R'
  1640.     endc
  1641.     ifne    popt        *printer option    flag
  1642. popflg:    dc.b    'P'
  1643.     endc
  1644.     ifne    sopt        *system    file option flag
  1645. sopflg:    dc.b    'S' 
  1646.     endc
  1647. oend    equ    *        *mark end of option table
  1648. *
  1649. * End of option    lookup table
  1650. *
  1651.     even
  1652. lincnt:    dc.b    0        *count of lines    printed    on screen
  1653. fndflg: dc.b    0        *flag whether any files matched
  1654. gotusr    dc.b    0
  1655. indent    dc.b    margsz        *size of left margin
  1656. mlps    dc.b    lps        *lines per screen (between pauses)
  1657. mnpl    dc.b    npl        *names per line (# of columns)
  1658. *
  1659. hlpmes:    dc.b    cr,lf,lf
  1660.     dc.b    'Correct usage:       SD {d}{u}:{filename.typ} '
  1661.     dc.b    '[option,option...]'
  1662.     dc.b    cr,lf,lf,'d = Drive, u = User and filespec are optional'
  1663.     dc.b    cr,lf,'Wildcards * and ? are supported'
  1664.     dc.b    cr,lf,lf,'Options available are:',cr,lf
  1665.     dc.b    cr,lf,tab,'[A]...All users '
  1666.     dc.b    tab,'[P]...Printed output'
  1667.     dc.b    cr,lf,tab,'[D]...all Drives'
  1668.     dc.b    tab,'[R]...unaRchived files'
  1669.     dc.b    cr,lf,tab,'[N]...No paging '
  1670.     dc.b    tab,'[S]...System files',cr,lf,lf,'$'
  1671. *
  1672. * Disk parameter block
  1673. *
  1674.     even
  1675. cdpb    ds.w    1    *number of 128-byte sectors on disk
  1676. blkshf    ds.b    1    *Block shift factor..# shifts to mult by sec/blk
  1677. blkmsk    ds.b    1    *Block mask...sec/blk - 1
  1678. exmsk    ds.b    1    *Extent mask
  1679. res168k    ds.b    1    *Reserved byte
  1680. blkmax    ds.w    1    *highest block # on drive
  1681. dirmax    ds.w    1    *highest file #    in directory
  1682. res268k    ds.w    1    *Reserved word
  1683. cks    ds.w    1    *length of checksum vector
  1684. trkoff    ds.w    1    *Track offset to disk directory
  1685. *
  1686. biosdma:ds.b    128
  1687. *
  1688. * Uninitialized    data area
  1689. *
  1690. basusr    ds.b    1    *dupe of original directory user # to search
  1691. colcnt    ds.b    1    *column count
  1692. count    ds.w    1    *entry count
  1693. freeby    ds.w    1    *contains number of k left on directory    drive
  1694. gap    ds.w    1    *sort routine storage
  1695. i    ds.w    1    *sort routine storage
  1696. j    ds.w    1    *sort routine storage
  1697. jg    ds.w    1    *sort routine storage
  1698. maxusr    ds.b    1    *maximum user #    for drive from lookup table
  1699. newusr    ds.b    1    *contains user number selected by "U" option
  1700. nextt    ds.l    1    *next table entry
  1701. olddsk    ds.b    1    *holder    for currently logged-in    drive
  1702. oldusr    ds.b    1    *contains user number upon invocation
  1703. scount    ds.w    1    *# to sort
  1704. supspc    ds.b    1    *leading space flag for    decimal    routine
  1705. tbloc    ds.l    1    *pointer to start of name table
  1706. tcount    ds.w    1    *temporary file count
  1707. temp    ds.w    1    *save dir entry
  1708. totfil    ds.w    1    *total number of files
  1709. totsiz    ds.w    1    *total size of all files
  1710. rorw    ds.b    1    *RW/RO flag
  1711. sysdir    ds.b    1    *Sys/Dir flag
  1712. arciv    ds.b    1    *Archive flag
  1713. stampon    ds.b    1    *Date/time stamp flag
  1714. tdflag    ds.b    1    *FCB number flag
  1715. tdate    ds.b    4    *Today's date and time
  1716. date1    dc.b    0    *1st byte of date from CP/M Plus SCB
  1717. date2    dc.b    0    *2nd byte of date from CP/M Plus SCB
  1718. hour    dc.b    0    *hour from CP/M Plus SCB
  1719. min    dc.b    0    *minute from CP/M Plus SCB
  1720. leapyr    dc.b    0    *leap year flag
  1721. yearda    dc.w    0    *number of the day of the year
  1722. extno    ds.b    1    *extent number
  1723. sectct    ds.b    1    *sector count of last extent
  1724.     even
  1725. numrec    ds.w    1    *number of records in file
  1726. order    equ    *    *order table starts here
  1727. *#######################################################################
  1728.     end
  1729.