home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-02-18 | 48.1 KB | 1,729 lines |
- *#######################################################################
- * Program SD...Directory Utility
- *
- * Dr. David C. Wilcox
- * DCW Industries, Inc.
- * 5354 Palm Drive, La Canada, CA 91011
- * 818/790-3844
- *
- * April 13, 1986
- *#######################################################################
- *
- * SPECIAL NOTE:
- * =============
- * This sorted directory utility has been created by translating the
- * CP/M-80 utility of the same name created by Bruce Ratliff from 8080
- * mnemonics to MC68000 mnemonics. I did the original work on a TRS-80
- * Model 16 with CP/M 68k running on top of CP/M Plus. Since CP/M Plus
- * supports time and date stamping, I chose to display time and date
- * stamps via special CP/M 68k bios calls to read the CP/M Plus time and
- * date stamp information. I have added a trs80 conditional assembly
- * flag which should exclude all such calls, but I have no way of testing
- * to see if I've done it correctly. Please let me know if there are
- * any problems and I'll try to provide fixes.
- * D.C. Wilcox
- *#######################################################################
- * Special registers:
- *
- * a5 = address of dma buffer
- * a6 = address of 1st parsed fcb
- *#######################################################################
- *
- false equ 0
- true equ $ff
- *
- * user option specifications
- *
- aopt equ true *true to allow searching all user areas
- dopt equ true *true to allow searching all drives on-line
- nopt equ true *true to allow disabling page pause option
- popt equ true *true to allow printer option
- ropt equ true *true to allow nonarchived file option
- sopt equ true *true to allow system file option
- uopt equ true *true to allow user number option
- *
- truek equ true *true to display actual file size
- trs80 equ false *true if TRS-80 Model 16 with CP/M Plus
- *
- break equ 03 *ascii etx (^C)
- tab equ 09 *horizontal tab
- lf equ 10 *line feed
- cr equ 13 *carriage return
- xoff equ 19 *ascii dc3 (^S)
- esc equ 27 *ascii escape
- space equ 32 *ascii space
- marker equ 33 *time/date stamping indicator
- upmask equ $5f *upper case mask
- *
- *delim equ 124 *fence (delimiter) character (vertical bar)
- delim equ 32 *space
- *delim equ 58 *colon
- *
- npl equ 02 *# of names per line (max of 2 for 80x24)
- margsz equ 10 *width of left margin indent
- lps equ 23 *# of lines per screen (max of 23 for 80x24)
- *
- drvmax equ 07 *maximum drive number (0=a:,1=b:...,7=h:)
- usrmax equ 15 *maximum user number (0-15)
- stskip equ 04 *start skipping at this drive number (1=a:,...)
- skipto equ 09 *and skip to this drive number (1=a:,...)
- *
- * bdos equates
- *
- boot equ 00 *warm boot
- rdchr equ 01 *read character from console
- wrchr equ 02 *write character to console
- listout equ 05 *output to LST:
- dirio equ 06 *direct console I/O
- pstring equ 09 *print a string
- const equ 11 *check console status
- seldsk equ 14 *select disk
- search equ 17 *search for first
- next equ 18 *search for next
- curdsk equ 25 *get currently logged disk name
- setdma equ 26 *set current dma
- curdpb equ 31 *get current disk parameters
- curusr equ 32 *get currently logged user number
- getfree equ 46 *get disk free space
- calbios equ 50 *direct bios call
- z80r equ $85 *read Z80 memory
- *
- bdos equ $0002 *bdos entry point
- bios equ $0003 *bios entry point
- *
- * Locate fcb and dma (for portability)
- *
- link a6,#0 *mark stack frame
- move.l 8(a6),a0 *get base page address
- lea $80(a0),a5 *get address of dma buffer
- lea $5c(a0),a6 *get address of 1st parsed file name
- jsr clear *Make sure key registers are clear
- start:
- move.w #$ff,d1 *get current user number
- move.w #curusr,d0
- trap #bdos
- move.b d0,oldusr *initialize startup user number
- move.b d0,newusr *..and make new user match it
- ifne dopt
- move.b d0,basusr *save extra copy for multi-disk
- endc *directories
- move.w #curdsk,d0
- trap #bdos *get current disk nr
- move.b d0,olddsk *save for reset if needed
- *
- * First we parse the dma to see if a user number has been entered.
- * If so, the fcb and dma are rewritten in normal CP/M syntax.
- *
- jsr parse
- *
- * Check to see if the fcb drive spec matches the currently logged
- * drive. If so, put a zero in the fcb since it's redundant.
- *
- jsr setdflt
- *
- * If at least one option is allowed, scan the command line for the
- * option field delimiter. Any unrecognized options or illegal user
- * numbers will cause the help message to print. (Note that we scan the
- * command line buffer rather than the 2nd default fcb because all 7
- * options plus a 2 digit user number won't fit in the fcb name field).
- *
- * Search for command line delimiter. If not found, assume no options.
- *
- clr.l d2
- movea.l a5,a2 *set command line buffer pointer
- move.b (a2)+,d2 *get length of command line buffer
- scndol:
- subq.b #1,d2
- blt ckrest *exit if command line buffer empty
- move.b (a2)+,d0
- cmpi.b #'[',d0 *option delimiter = "["
- bne scndol
- *
- * Valid delimiter found. Scan the rest of the buffer for options.
- * Errors past this point cause an abort.
- *
- scnopt:
- subq.b #1,d2 *dock characters left in option field
- blt ckrest *if option field exhausted, exit
- scnagn: move.b (a2)+,d0 *get the next option character
- cmpi.b #space,d0 *do we have a space?
- beq scnopt *ignore it if so
- cmpi.b #',',d0 *same for comma
- beq scnopt
- cmpi.b #']',d0 *end of option list
- beq ckrest
- movea.l #otbl,a0 *get base of option lookup table
- subq #1,a0
- move.l #oend,a1 *get length of option lookup table
- suba.l a0,a1
- move.l a1,d1
- nomach: addq #1,a0 *bump to next option table character
- subq.b #1,d1 *are we out of the table?
- beq ck4usr *if so, check for user option
- cmp.b (a0),d0 *compare our character with option table
- bne nomach *exit if no match
- move.b #0,(a0) *otherwise, activate the flag
- bra scnopt *..and go get the next option character
- *
- * If option character doesn't match the table, see if we have a user
- * option.
- *
- ck4usr: nop
- ifne uopt *check for user number option
- cmpi.b #'U',d0
- bne clerr *last option
- uagn: subq #1,d2 *bump to user number digit
- blt clerr *error if nothing left
- move.b (a2)+,d0 *get decimal digit
- cmpi.b #space,d0 *ignore leading spaces
- beq uagn
- subi.b #$30,d0 *subtract ascii bias
- blt clerr *error if < 0
- cmpi.b #10,d0
- bgt clerr *error if > 9
- move.b d0,newusr *save user number as it may be 1 digit
- ifne dopt
- move.b d0,basusr *duplicate it if multi-disk mode
- move.b #$ff,gotusr *set got user flag
- endc
- subq.b #1,d2 *bump to possible 2nd digit of user no.
- blt ckrest *if no more buffer, exit with user #
- move.b (a2),d0 *else, check for another digit
- subi.b #$30,d0
- blt scnagn *if next char not numeric, it's not part
- cmpi.b #10,d0 *of user no. so check for another option
- bgt scnagn
- movea.l #newusr,a1 *get tens digit
- move.b (a1),d1
- mulu #10,d1 *multiply by 10
- add.b d1,d0 *combine with units digit
- move.b d0,(a1) *save the total user number
- addq #1,a2 *point to next option
- ifne dopt
- move.b d0,basusr *duplicate it if multi-disk mode
- endc
- bra scnopt *continue scanning
- endc *balance uopt
- *
- * If command line error occurs, say so and display instructions on
- * correct usage.
- *
- clerr:
- movea.l #synerr,a0 *display "syntax error" in reverse video
- jsr print
- bra help *..and display help message
- *
- * Options input or not specified. Get today's date & time before
- * proceeding any further.
- *
- ckrest: nop
- ifne trs80
- jsr today
- endc
- *
- * If "A" option choosen and no user number specified
- * set user to zero
- *
- zusr: nop
- ifne aopt
- movea.l #gotusr,a0 *was a user specified?
- cmpi.b #0,(a0)
- bne zdrv *yes-quit now
- movea.l #aopflg,a0 *was "A" option specified?
- cmpi.b #0,(a0)
- bne zdrv *branch if no
- move.b #0,newusr *zero newusr for all users
- ifne dopt
- move.b #0,basusr *zero basusr for all users
- endc
- endc
- *
- * If "D" option choosen and no drive specified
- * set drive to physical zero
- *
- zdrv: move.b (a6),d0 *get drive name for directory search
- cmpi.b #0,d0 *any specified?
- bne noopt *skip next routine if drive specified
- ifne dopt
- movea.l #dopflg,a0 *else if dopt then
- cmpi.b #0,(a0)
- bne zdrv1
- move.b #1,(a6) *always start with a:
- bra noopt
- endc
- zdrv1: movea.l #olddsk,a0 *otherwise, get default disk
- move.b (a0),d0
- addq.b #1,d0
- move.b d0,(a6) *put the absolute drive code in fcb
- *
- * Validate drive code and user area number.
- *
- noopt: movea.l #dremsg,a0 *get the drive/user error message
- move.b (a6),d0 *get directory drive code
- subq.b #1,d0 *normalize to range of 0-7
- cmpi.b #drvmax,d0 *compare with maximum drives on-line
- bgt erxit *take drive error exit if out of range
- movea.l #usrmsg,a0 *switch to user # error message
- movea.l #maxusr,a1
- move.b #usrmax,(a1) *store max user # in maxusr
- movea.l #newusr,a1 *point to the directory user area
- move.b (a1),d0
- cmpi.b #usrmax,d0 *compare it with the maximum
- bgt erxit *take error exit if user number illegal
- movea.l a6,a1 *point to first character in fcb
- addq #1,a1
- cmpi.b #'[',(a1)
- beq gotdl
- cmpi.b #space,(a1)
- bne gotfcb
- *
- * If no fcb...make fcb all '?'
- *
- gotdl: moveq.l #11,d2 *fn+ft count
- qloop: move.b #'?',(a1)+ *store '?' in fcb
- subq #1,d2
- bne qloop
- gotfcb: move.b #'?',12(a6) *force wild extent
- jsr setsrc *set dma for bdos media change check
- move.b (a6),d1 *get the drive code out of the fcb
- subq #1,d1 *normalize drive code for select
- move.b #seldsk,d0 *select the directory drive to retrieve
- trap #bdos *..the proper allocation vector
- move.l #cdpb,d1 *request dpb
- move.w #curdpb,d0
- trap #bdos
- *
- * Calculate # of kbytes free on selected drive
- *
- free: clr.l d1
- move.b (a6),d1 *get drive #
- subq #1,d1
- move.w #getfree,d0 *use compute free space bdos call
- trap #bdos
- move.l (a5),d0
- divu #8,d0 *convert from sectors to kbytes
- move.w d0,freeby *save free space for output later
- *
- * Check for presence of time and date stamps
- *
- move.b #2,mnpl *reset column counter to 2
- jsr chkstmp *check for date/time stamps
- movea.l #stampon,a0
- cmp.b #$20,(a0) *are they present?
- beq settbl *yes...stay with 2 column display
- move.b #3,mnpl *no....change to a 3 column display
- *
- * Reenter here on subsequent passes while in the all-users mode
- *
- settbl: clr.l d2
- movea.l #dirmax,a0 *get directory maximum again
- move.w (a0),d2
- addq.w #1,d2 *directory size is dirmax+1
- mulu #4,d2 *quadruple directory size
- movea.l #order,a1 *to get size of order table
- add.l d2,a1 *allocate order table
- movea.l #tbloc,a0 *name table begins where
- move.l a1,(a0)
- move.l a1,nextt *order table begins
- ifne uopt
- clr.l d1
- movea.l #newusr,a0 *get user area for directory
- move.b (a0),d1
- move.w #curusr,d0 *get the user function
- trap #bdos *..and set new user number
- endc
- *
- * Look up the fcb in the directory
- *
- sfirst: move.w #0,count *initialize match counter
- move.w #0,totfil *initialize total file counter
- move.w #0,totsiz *initialize total size counter
- jsr setsrc *set dma for directory search
- move.w #search,d0 *get 'search first' function
- bra look *..and go search for 1st match
- *
- * Read more directory entries
- *
- mordir: move.w #next,d0 *search next
- look: move.l a6,d1
- trap #bdos *read directory entry
- cmpi.b #$ff,d0 *check for end ($ff)
- beq sprint *if no more, sort & print what we have
- *
- * Point to directory entry
- *
- some: move.b d0,tdflag *save it for retrieving date stamp
- mulu #32,d0 *compute directory offset
- movea.l a5,a2 *point to dma buffer
- add.l d0,a2 *point to entry
- adda.l #10,a2 *point to sys byte
- ifne ropt
- movea.l #ropflg,a0 *did user request unarchived
- cmpi.b #0,(a0) *files only?
- bne anyarc
- adda.l #1,a2 *point to arc byte
- btst #7,(a2) *check bit 7 of arc byte
- bne mordir *skip if it's archived
- suba.l #1,a2 *now point to sys bit for proper
- bra sysfok *alignment...then skip sys bit check
- endc
- anyarc: nop
- ifne sopt
- movea.l #sopflg,a0 *did user request sys files?
- move.b (a0),d0
- cmpi.b #0,d0
- beq sysfok
- endc
- btst #7,(a2) *check bit 7 of sys byte
- bne mordir *skip that file
- sysfok: suba #10,a2 *back to user number (alloc flag)
- movea.l #newusr,a0 *get current user
- cmpm.b (a0)+,(a2)+
- bne mordir *ignore if different
- *
- * Move entry to table
- *
- movea.l #nextt,a0 *next table entry to...
- move.l (a0),a3 *register a3
- moveq.l #12,d2 *entry length (name, type, extent)
- tmove: move.b (a2)+,(a3)+ *store entry character in table
- subq #1,d2 *more?
- bne tmove
- adda #2,a2 *point to sector count
- move.b (a2)+,(a3)+ *store in table
- cmpi.b #$20,stampon *check for date stamp enabled
- beq savdat *enabled...so retrieve date stamp
- adda #5,a3 *otherwise, skip over five bytes
- bra tmove1
- savdat: movea.l #tdflag,a0 *fetch fcb number
- clr.l d0
- move.b (a0),d0
- mulu #10,d0 *calculate time/date stamp offset
- addi.b #101,d0
- movea.l a5,a2 *point to beginning of dma buffer
- add d0,a2 *add time/date stamp offset
- moveq.l #4,d2
- loopdat:move.b (a2)+,(a3)+ *copy time/date stamp data
- subq #1,d2 *in table
- bne loopdat
- move.b #0,(a3)+ *pad with a null byte
- tmove1: move.l a3,nextt *save updated table addr
- addq.w #1,count *bump the # of matches made
- bra mordir
- *
- * Sort and print
- *
- sprint: nop
- ifne aopt or uopt
- jsr setfop *return to file output dma & user #
- endc
- movea.l #count,a0 *get file name count
- movea.l #tcount,a4
- move.w (a0)+,(a4)+
- cmpi.w #0,tcount *any found?
- beq prtotl *exit if no files found
- move.b #1,supspc *enable leading zero suppression
- subq #2,a4 *make a4 point to tcount
- *
- * Initialize the order table
- *
- movea.l #tbloc,a0 *get start of name table
- move.l (a0),a2
- movea.l #order,a1 *point to order table
- bldord: move.l a2,(a1)+ *save address
- adda #18,a2 *point to next entry (add 18 bytes)
- subq #1,(a4) *count down loop
- bne bldord *if nonzero, do another one
- movea.l #count,a0 *get count
- move.w (a0),scount *save as # to sort
- cmpi.b #1,(a0) *only 1 entry?
- beq noout *yes, so skip sort
- *
- * This sort routine is adapted from (8080) software tools
- * by Kernigan and Plaugher. I'm sure it can be improved
- * upon, and has probably been written for the MC68000 long
- * ago...BUT...each day only has 24 hours! I simply translated
- * the 8080 routine.
- *
- sort: clr.l d0
- clr.l d1
- clr.l d4
- movea.l #scount,a3 *number of entries
- l0: clr.l d3 *clear carry
- move.w (a3),d3 *gap=gap/2
- divu #2,d3
- cmpi.w #0,d3 *is it zero?
- beq noout *then none left
- ori.b #1,d3 *make gap odd
- move.w d3,gap
- addq.w #1,d3 *i=gap+1
- l2: move.w d3,i
- movea.l #gap,a3
- move.w (a3),d4 *j=i-gap
- sub.w d4,d3
- l3: move.w d3,j
- movea.l #gap,a3 *jg=j+gap
- move.w (a3),d4
- add.w d3,d4
- move.w d4,jg
- move.w d4,d0
- move.w d3,d1
- jsr compare *compare (j) and (jg)
- bgt l5 *if a(j)<=a(jg)
- movea.l #j,a3
- move.w (a3),d0
- movea.l #jg,a3
- move.w (a3),d1
- jsr swap *exchange a(j) and a(jg)
- movea.l #j,a3 *j=j-gap
- move.w (a3),d3
- movea.l #gap,a3
- move.w (a3),d4
- sub.w d4,d3
- blt l5 *if j>0 goto l3
- cmpi.w #0,d3 *check for zero
- beq l5
- bra l3
- l5: movea.l #scount,a3 *for later
- move.w (a3),d4
- movea.l #i,a3 *i=i+1
- move.w (a3),d3
- addq.w #1,d3
- cmp.w d3,d4 *if i<=n goto l2
- bge l2
- movea.l #gap,a3
- bra l0
- *
- * Sort is all done - print entries
- *
- noout:
- movea.l #order,a3 *initialize order table pointer
- move.l a3,nextt
- jsr crlf *print "directory for ...
- movea.l #dirms1,a0 *at start of each section
- jsr print
- jsr prdir2 *print " drive, x user, y"
- ifne trs80
- movea.l #datmsg,a0 *print " Date: "
- jsr print
- jsr loadtd *put today's date in appropriate memory
- jsr display *print today's date & time
- endc
- jsr crlf
- movea.l #linmsg,a0
- jsr print
- addq.b #1,lincnt *bump line count
- bra newlin *start new line and output the files
- *
- * Output the directory files we've matched.
- *
- entry: subq #1,count *dock file count
- beq okprnt *if count=0, last file so skip compare
- *
- * Compare each entry to make sure that it isn't part of a multiple
- * extent file. Go only when we have the last extent of the file.
- *
- jsr ckabrt *check for abort code from keyboard
- movea.l #nextt,a2
- move.l (a2),a3
- move.l (a3)+,a1
- move.l (a3),a0
- jsr compr *does this entry match next one?
- bne okprnt *no, print it
- cmpi.b #$20,stampon *check for date stamps on
- bne nocarry
- jsr carry *carry date stamp forward
- nocarry:
- move.l a3,nextt *skip since highest extent comes last
- bra entry *loop back for next lowest extent
- *
- * Valid entry obtained - display it.
- *
- okprnt: movea.l #nextt,a2 *get order table pointer
- move.l (a2),a3 *get address
- move.l (a3)+,a1
- move.l a3,nextt *save updated table pointer
- moveq.l #8,d2 *file name length
- jsr typeit *type filename
- move.b #'.',d1 *period after filename
- jsr type
- jsr savatrb *save attribute flags
- moveq.l #3,d2 *display 3 characters of filetype
- jsr typeit
- *
- * Compute the size of the file and update our summary datum.
- *
- move.b (a1)+,extno *get extent number
- move.b (a1)+,sectct *get sector count of last extent
- move.b (a1)+,date1 *1st date byte
- move.b (a1)+,date2 *2nd date byte
- move.b (a1)+,hour *hour
- move.b (a1)+,min *munute
- movea.l #extno,a0
- clr.l d0
- move.b (a0),d0 *multiply number of
- mulu #16,d0 *extents by 16k
- *
- ifne truek
- jsr calcrec *calculate number of records
- divu #8,d0 *convert to kbytes
- move.l d0,d1
- swap d1 *examine remainder
- cmpi.w #0,d1 *is it zero?
- beq fini *yes...no leftover sectors
- addq.w #1,d0 *no....add another kbyte
- endc
- *
- ifeq truek
- movea.l #blkmsk,a0
- movea.l #sectct,a1 *round last extent to block size
- clr.l d1
- move.b (a1),d1
- add.b (a0),d1
- divu #8,d1 *convert from sectors to k
- add.b d1,d0 *add to total k
- clr.l d1
- move.b (a0),d1 *convert sec/blk to k/blk
- divu #8,d1
- not.b d1 *use to finish rounding
- and.b d1,d0
- endc
- *
- fini: add.w d0,totsiz *add to total used
- addq.w #1,totfil *increment file count
- move.w d0,d4 *save it in d4
- *
- * Output the size of the individual file.
- *
- move.b #space,d1 *begin with a space
- jsr type
- jsr decprt *print file size
- move.b #'k',d1 *follow with 'k'
- jsr type
- move.b #space,d1 *and conclude with a space
- jsr type
- *.......................................................................
- * Output the number of records of the individual file
- *
- * movea.l #numrec,a0 *point to total records
- * move.w (a0),d4
- * jsr decprt *print number of records
- *.......................................................................
- * Display attributes
- *
- cmpi.b #$80,rorw *check RO/RW flag
- bne unpro
- move.b #'R',d1
- bra syschk
- unpro: move.b #space,d1
- syschk: jsr type
- cmpi.b #$80,sysdir *check Sys/Dir flag
- bne unsys
- move.b #'S',d1
- bra arcchk
- unsys: move.b #space,d1
- arcchk: jsr type
- cmpi.b #$80,arciv *check Archive flag
- bne unarc
- move.b #'A',d1
- bra alldone
- unarc: move.b #space,d1
- alldone:
- jsr type
- move.b #space,d1 *print a space
- jsr type
- cmpi.b #$20,stampon
- bne nodisp
- jsr display *now the date and time
- *
- * One file output - test to see if we have to output another one.
- *
- nodisp: movea.l #count,a2 *get current file counter and test it
- cmpi.w #0,(a2)
- beq prtotl *if no more files, go to summary output
- *
- * At least one more file to output - can we put it on the current line?
- *
- subq.b #1,colcnt
- beq nodis1
- jsr fence *if room left, output column separator
- nodis1: cmpi.b #0,colcnt
- bne entry *.. and go output another file
- *
- * Current line full, start a new one.
- *
- newlin: movea.l #mnpl,a0
- move.b (a0),colcnt *reset names per line counter
- jsr crlf *space down to next line
- bra entry *go back and output another file
- *
- * Print d4 in decimal with leading zero suppression
- *
- decprt: move.b #0,d5 *clear leading zero flag
- movea.l #supspc,a0 *get leading space suppression flag
- move.b (a0),d6
- clr.l d3 *print 1000's digit
- move.w d4,d3
- divu #1000,d3
- move.l d3,d4
- jsr digit
- swap d4
- clr.l d3 *print 100's digit
- move.w d4,d3
- divu #100,d3
- move.l d3,d4
- jsr digit
- swap d4
- clr.l d3 *print 10's digit
- move.w d4,d3
- divu #10,d3
- move.l d3,d4
- jsr digit
- swap d4
- move.w d4,d1 *print units digit
- addi.b #'0',d1
- bra type
- digit: move.b d3,d1
- addi.b #'0',d1
- digex: cmpi.b #'0',d1 *zero digit?
- bne dignz *no, type it
- cmpi.b #0,d5 *leading zero?
- bne type *print digit
- cmpi.b #0,d6 *is space suppression flag set?
- bne digsp *no....print a leading space
- rts *yes...don't give leading spaces
- digsp: bra pspace *leading zero...print space
- dignz: move.b #1,d5 *set leading zero flag so next zero
- bra type *prints, and print digit
- *
- * Show total space and files used
- *
- prtotl:
- move.b #0,supspc *suppress leading spaces in totals
- movea.l #totfil,a0 *how many files did we match?
- move.w (a0),d0
- cmpi.w #0,d0
- beq nxtusr *skip the summary if we didn't find any
- move.b #1,fndflg *set file found flag
- jsr crlf
- jsr prdir *print " drive, x user, y"
- nouser: movea.l #totms3,a0 *print " contains "
- jsr print
- clr.l d4
- movea.l #totsiz,a0 *print total k used by files matched
- move.w (a0),d4
- jsr decprt
- movea.l #totms4,a0 *print "k in "
- jsr print
- clr.l d4
- movea.l #totfil,a0 *recall totfil
- move.w (a0),d4
- jsr decprt *print number of files matched
- movea.l #totms5,a0 *print " files with "
- jsr print
- jsr prtfre *output free space remaining & " free"
- *
- * Directory for one user area completed. If all users option is
- * selected, then go do another directory on the next user number
- * until we exceed the maximum user # for the selected drive.
- *
- nxtusr: nop
- ifne aopt *if all users option enabled
- movea.l #aopflg,a0 *if not all users mode - skip next
- cmpi.b #0,(a0)
- bne goclz
- jsr ckabrt *check for user abort first
- movea.l #newusr,a1 *bump directory user number
- addq.b #1,(a1)
- cmpi.b #usrmax,(a1) *does next user # exceed maximum?
- blt settbl *continue if more user areas to go
- endc *aopt
- ifne dopt and aopt *if multi-disk option enabled
- movea.l #basusr,a0 *reset base user number for the
- move.b (a0),newusr *..next directory search
- endc *balance dopt and aopt
- *
- * We've finished all of our outputting. Flush the remainder of the
- * output buffer and close the file before going to exit routine.
- *
- goclz: nop
- *
- * Directory for all user areas completed. If the multi-disk option
- * is enabled and selected, reset to the base user area and repeat
- * the directory for next drive on-line until we either exceed the
- * drives on line, or the BDOS shuts us down with a select or bad
- * sector error, which will be intercepted back to the exit module.
- *
- nxtdsk: movea.l #fndflg,a0 *get file found flag
- move.b (a0),d0
- move.b #0,(a0) *clear file found flag for next drive
- cmpi.b #0,d0
- bne ndsk *continue if at least 1 file found
- move.b (a6),d0 *stash ascii directory drive
- addi.b #'A'-1,d0 *in no file message
- move.b d0,nofms2
- jsr crlf
- movea.l #nofms1,a0 *print "no file on ? - "
- jsr print
- jsr prtfre *tag with free message
- ndsk: nop
- ifne dopt *if multi-disk option enabled
- movea.l #dopflg,a0 *if multi-disk not selected - skip next
- cmpi.b #0,(a0)
- bne nprt
- jsr ckabrt *check for user abort first
- addq.b #1,(a6) *bump directory fcb drive code
- cmpi.b #stskip,(a6) *skip if start skip
- bne next1
- move.b #skipto,(a6) *if stskip then skipto
- next1: cmpi.b #drvmax,(a6) *does next disk exceed maximum?
- ble noopt *search next disk if not
- endc *balance dopt
- nprt: nop *if no printer, fall through to exit
- ifne popt *now, check if printer is in use
- movea.l #popflg,a0
- cmpi.b #0,(a0) *printer active?
- bne exit *no, just exit...
- move.w #listout,d0
- move.b #cr,d1 *print a carriage return
- trap #bdos
- move.b #lf,d1 *and a line feed
- trap #bdos
- endc *popt
- bra exit *all done - exit to ccp
- *
- * Print "directory for....
- *
- prdir: movea.l #linmsg,a0
- jsr print
- jsr crlf
- jsr margin *set the margin
- prdir2: movea.l #totms1,a0 *print " Drive "
- jsr print
- movea.l a6,a0 *point to fcb
- move.b (a0),d1
- add.b #'A'-1,d1
- jsr type *output the drive code
- movea.l #totms2,a0 *print ", user "
- jsr print
- jsr typusr *output the user number
- prdir1: rts
- *
- * Print the user number of the directory in decimal
- *
- typusr: movea.l #newusr,a0
- move.b (a0),d2
- cmpi.b #10,d2 *if user no. > 9 print leading 1
- blt dux
- move.b #'1',d1
- jsr type
- subi.b #10,d2 *extract low digit of user no.
- dux: addi.b #'0',d2 *make it ascii
- move.b d2,d1 *and display it
- bra type
- *
- * Force new line on video and check for page pause
- *
- crlf: move.b #cr,d1 *send cr
- jsr type
- move.b #lf,d1 *send lf
- bra type *exit to caller from type
- *
- * Separate the directory output on a line with two spaces,
- * the delimiter, followed by two more spaces.
- *
- fence: jsr pspace
- jsr pspace
- move.b #delim,d1 *fence character
- jsr type *print it, fall into space
- move.b #space,d1
- jsr type
- pspace: move.b #space,d1 *fall through to type
- *
- * Output character in d1 to console, and optionally to printer.
- *
- type:
- jsr type1 *send it to console
- andi.b #$7f,d1 *strip parity bit on character
- *
- * Test file output mode and skip to page pause test if not active.
- *
- ifne popt *if printer option
- movea.l #popflg,a3 *test printer flag
- cmpi.b #0,(a3)
- bne cheklf
- move.w #listout,d0 *setup list output call
- trap #bdos *print character if flag true
- endc
- cheklf: cmpi.b #lf,d1 *do we have a lf?
- bne typret *exit if not
- ifne nopt
- movea.l #nopflg,a3 *is the page pause function disabled?
- cmpi.b #0,(a3)
- beq typret *exit if so
- endc
- movea.l #lincnt,a3 *get line count
- move.b (a3),d0
- addq.b #1,d0 *bump it
- cmpi.b #lps,d0 *are we at the end of the screen?
- blt noteos *skip if not
- move.l #eosmsg,d1 *else, display pause message
- move.w #pstring,d0 *..without checking for lfs
- trap #bdos
- jsr cinput *wait for character
- cmpi.b #break,d0
- beq exit *abort on ^C
- move.b #0,d0 *reset line count
- noteos: move.b d0,(a3) *save new line count
- typret: rts *exit from type
- *
- * Output character
- *
- type1:
- move.w #wrchr,d0
- trap #bdos *call conout via the bdos
- rts
- *
- * Print a string at a1 of length d2
- *
- typeit: move.b (a1)+,d1
- jsr type
- subq #1,d2
- bne typeit
- rts
- *
- * Print string terminated with '$' character by character.
- *
- print: move.b (a0)+,d1 *get a character
- cmpi.b #'$',d1 *is it the end of the string?
- bne print1
- rts *yes...return
- print1: and.b #$7f,d1 *no....strip parity bit
- jsr type *display it
- bra print *and loop back for another character
- *
- * Fetch character from console (without echo)
- *
- cinput: move.w #$ff,d1
- move.w #dirio,d0
- trap #bdos
- andi.b #$7f,d0
- rts
- *
- * Check for a ^C or ^S entered from the keyboard. Jump to exit
- * if ^C...pause on ^S.
- *
- ckabrt: move.w #$fe,d1 *check status of keyboard
- move.w #dirio,d0
- trap #bdos
- cmpi.b #0,d0 *any key pressed?
- bne get1
- rts *no, return to caller
- get1: jsr cinput *get character
- cmpi.b #break,d0 *is it ^C?
- beq exit *if ^C then quit
- cmpi.b #xoff,d0 *is it ^S?
- beq get2 *yes, wait for another character
- rts *no, return to caller
- get2: jsr cinput
- cmpi.b #break,d0 *might be ^C
- beq exit *exit if ^C else fall thru & continue
- rts
- *
- * For file output mode, return to old user area and set dma for
- * the file output buffer.
- *
- setfop: nop
- ifne uopt or aopt
- movea.l #oldusr,a0 *get user number at startup
- clr.l d1
- move.b (a0),d1
- move.w #curusr,d0
- trap #bdos *reset the old user number
- endc
- rts
- *
- * Move disk buffer dma to default buffer for directory search operations
- * and bdos media change routines.
- *
- setsrc:
- move.l a5,d1
- move.w #setdma,d0
- trap #bdos
- clr.l d1
- rts
- *
- * Print the amount of free space remaining on the selected drive.
- *
- prtfre: clr.l d4
- movea.l #freeby,a0 *get space left
- move.w (a0),d4
- jsr decprt *print k free
- movea.l #totms6,a0 *print " free"
- bra print
- *
- * Compare two consecutive files for possible multiple extents
- *
- compr:
- move.l #11,d2 *compare fn, ft
- cmplp: move.b (a0)+,d0
- andi.b #$7f,d0
- move.b (a1)+,d1
- andi.b #$7f,d1
- cmp.b d1,d0
- beq domor
- rts
- domor: subq #1,d2
- bne cmplp
- rts
- *
- * Swap entries in the order table
- *
- swap:
- movea.l #order-4,a2 *table base
- mulu #4,d0 *index x 4
- move.l d0,a0
- adda.l a2,a0 *+ base
- mulu #4,d1 *index x 4
- move.l d1,a1
- adda.l a2,a1 *+ base
- move.l (a0),d0
- move.l (a1),d1
- move.l d0,(a1)
- move.l d1,(a0)
- rts
- *
- * Compare routine - modified for filetype sort
- *
- compare:
- movea.l #order-4,a2 *table base
- mulu #4,d0 *index x 4
- move.l d0,a3
- adda.l a2,a3 *+ base
- move.l (a3),a0
- mulu #4,d1 *index x 4
- move.l d1,a4
- adda.l a2,a4 *+ base
- move.l (a4),a1
- *
- * Compare by filename, filetype, extent - in that order
- *
- cmpfnft:
- move.l #12,d2 *compare fn, ft, ex
- cmplpe: move.b (a0)+,d0
- andi.b #$7f,d0
- move.b (a1)+,d1
- andi.b #$7f,d1
- cmp.b d1,d0
- beq domore
- rts
- domore: subq #1,d2
- bne cmplpe
- rts
- *
- * Print a short help message
- *
- help: move.l #hlpmes,d1
- move.w #pstring,d0
- trap #bdos
- bra exit
- *
- * Error exit
- *
- erxit: jsr print *print first part of message
- movea.l #errms1,a0 *print " Error"
- jsr print
- jsr crlf *space down
- *
- * Exit - all done
- *
- exit: move.w #const,d0 *check console status
- trap #bdos
- cmpi.b #0,d0 *char waiting?
- beq exit1 *no...return to CP/M
- move.w #rdchr,d0 *otherwise...
- trap #bdos *gobble up char
- exit1: move.w #boot,d0 *..and return to CP/M
- trap #bdos
- *
- * Recovery point from intercepted bdos select and bad sector errors.
- *
- ifne dopt
- dskerr: bra exit *..and exit back to ccp
- endc
- *
- * calculate number of records in file
- *
- calcrec:
- mulu #8,d0 *convert extent count to records
- clr.l d1
- movea.l #sectct,a0 *now add the # of records
- move.b (a0),d1 *in the final extent
- add.w d1,d0 *d0 now contains # of records
- move.w d0,numrec *save it in numrec and
- rts *...return
- *
- * Clear all data registers
- *
- clear:
- clr.l d0
- clr.l d1
- clr.l d2
- clr.l d3
- clr.l d4
- clr.l d5
- clr.l d6
- clr.l d7
- rts
- *
- * Indent left margin
- *
- margin:
- clr.l d2
- movea.l #indent,a0
- move.b (a0),d2
- repeat: jsr pspace
- subq #1,d2
- bge repeat
- rts
- *
- * Move d2 bytes from a1 to a0
- *
- movmem:
- move.b (a1)+,(a0)+
- subq #1,d2
- bne movmem
- rts
- *
- * Save attribute flags
- *
- savatrb:
- movea.l a1,a2
- move.b (a2)+,d0 *check RO/RW flag
- andi.b #$80,d0
- move.b d0,rorw *save it in rorw
- move.b (a2)+,d0 *check Sys/Dir flag
- andi.b #$80,d0
- move.b d0,sysdir *save it in sysdir
- move.b (a2)+,d0 *check Archive flag
- andi.b #$80,d0
- move.b d0,arciv *save it in arciv
- rts
- *
- * Check for drivespec = logged drive and set fcb if it is
- *
- setdflt:
- cmpi.b #0,(a6) *is it the default drive?
- bne morchk *no....must check further
- rts *yes...return
- morchk: movea.l #olddsk,a4 *point to currently logged drive
- move.b (a4),d0 *put it in d0
- addq.b #1,d0 *make it absolute
- cmp.b (a6),d0 *is it the same as the specified drive?
- beq mkdflt *yes...make the fcb contain a zero
- rts *no....return
- mkdflt: move.b #0,(a6) *first byte in fcb = 0
- rts
- *
- *#######################################################################
- * Special DMA Parsing Subroutines
- *#######################################################################
- *
- * Check dma for user area specified as part of drive specification
- *
- parse:
- movea.l a5,a4 *point to dma
- move.b (a4),d7 *get length of command string
- cmpi.b #0,d7 *no command tail?
- beq finish
- move.b #1,d5
- char1: adda #1,a4 *point to next character
- cmpi.b #space,(a4) *is it a space?
- bne gotch1 *no....mark its position
- addq #1,d5 *yes...bump position marker
- subq #1,d7 *1 less character remaining
- bne char1 *check next character
- rts *all done if no more characters
- gotch1: cmpi.b #'[',(a4) *is it a '['?
- beq finish *all done, no drive specified
- subq #1,d7 *dock characters remaining
- beq finish *all done if no more
- add.b d5,d6 *bump marker to next position
- colon: adda #1,a4 *now look for a ':'
- cmpi.b #':',(a4) *is it a ':'?
- beq gotcln *yes...mark its position
- cmpi.b #'[',(a4) *is it a '['?
- beq finish *all done, no drive specified
- addq #1,d6 *no...bump position marker
- subq #1,d7 *1 less character remaining
- beq finish *all done if no more characters
- bra colon *check next character
- gotcln: addq.b #1,d6 *increment marker one more time
- sub.b d5,d6 *compute their difference
- cmpi.b #1,d6 *is it 1?
- beq finish *yes...no rearrangement necessary
- try2: cmpi.b #2,d6 *is it 2?
- beq onedig *yes...it's a one digit user
- cmpi.b #3,d6 *is it 3?
- beq twodig *yes...it's a two digit user
- move.l #synerr,d1 *otherwise, we have an error
- move.w #pstring,d0 *say so and quit
- trap #bdos
- bra help
- onedig: suba #2,a4 *back up to drive designator
- move.b (a4)+,d0 *get drive designator
- move.b d0,drive *save it in drive
- move.b (a4)+,d0 *get user number
- move.b d0,tail+2 *save it
- move.b #']',tail+3 *append a ']'
- bra fixfcb *go fix up the fcb
- twodig: suba #3,a4 *back up to drive designator
- move.b (a4)+,d0 *get drive designator
- andi.b #upmask,d0 *make it upper case
- move.b d0,drive *save it in drive
- move.b (a4)+,d0 *get first digit of user number
- move.b d0,tail+2 *save it
- move.b (a4)+,d0 *get second digit of user number
- move.b d0,tail+3 *save it
- move.b #']',tail+4 *append a ']'
- fixfcb: subq #1,d7 *dock characters remaining
- beq stuff *no file name...go stuff the fcb
- movea.l #fname,a3 *point to file name storage buffer
- move.l #8,d2 *8 characters max
- getnam: adda #1,a4 *point to next character
- move.b (a4),d0 *get it
- cmpi.b #'[',d0 *is it a '['?
- beq stuff *yes...we have the whole file name
- cmpi.b #'.',d0 *is it a '.'?
- beq gettyp *yes...file type follows
- move.b d0,(a3)+ *save the character
- subq #1,d2 *dock file name char counter
- beq getdot *we have all 8 characters...strip '.'
- subq #1,d7 *dock characters remaining
- beq stuff *out of characters...go stuff the fcb
- bra getnam *go back for another character
- getdot: subq #1,d7 *dock characters remaining
- beq stuff *no more left...go stuff the fcb
- adda #1,a4 *otherwise point to next character
- move.b (a4),d0 *get it
- cmpi.b #'[',d0 *is it a '['?
- beq stuff *yes...go stuff the fcb
- cmpi.b #'.',d0 *is it a '.'?
- beq gettyp *yes...skip over it
- move.l #synerr,d1 *no....this is incorrect
- move.w #pstring,d0 *say so and quit
- trap #bdos
- bra help
- gettyp: subq #1,d7 *dock characters remaining
- beq stuff *no type given...go stuff the fcb
- movea.l #ftype,a3 *point to file type buffer
- move.l #3,d2 *3 characters max
- gettyp1:adda #1,a4 *point to next character
- move.b (a4),d0 *get it
- cmpi.b #'[',d0 *is it a '['?
- beq stuff *yes...we have the whole file type
- move.b d0,(a3)+ *save the character
- subq #1,d2 *dock file type char counter
- beq stuff *we have all 3 chars...go stuff fcb
- subq #1,d7 *dock characters remaining
- beq stuff *no more left...go stuff fcb
- bra gettyp1 *go back for another character
- stuff: movea.l #fname,a3 *parse file name and make
- move.l #8,d2 *upper case...also, expand '*'
- jsr wldfil *to a string of ?'s
- movea.l #ftype,a3 *parse file type and make
- move.l #3,d2 *upper case...also, expand '*'
- jsr wldfil *to a string of ?'s
- movea.l #drive,a1 *get drive designator
- subi.b #'A'-1,(a1) *make it a number
- move.l #12,d2 *finally, copy all to the fcb
- movea.l a6,a0 *point to fcb
- jsr movmem *and do the copy
- fixdma: movea.l a5,a0 *now see if we have any options
- move.b (a0),d7 *get character count
- move.b d7,d6 *save it in d6
- lbrak: addq #1,a0 *point to next character
- cmpi.b #'[',(a0) *is it the delimiter?
- beq gotlb *yes...exit this loop
- subq #1,d7 *dock counter
- beq nolb *no options specified
- bra lbrak *go back for another character
- gotlb: subq #1,d7 *dock counter
- beq nolb *funny case...but add tail anyhow
- rbrak: adda #1,a0 *point to next character
- cmpi.b #']',(a0) *is it ']'?
- beq adtail *yes...go add the tail
- subq #1,d7 *no....dock the counter
- beq adtail *out of chars...add the tail
- bra rbrak *go back for another character
- adtail: movea.l #tail+1,a1 *point to user spec without '['
- move.l #5,d2
- jsr movmem *and copy tail to dma
- addi.b #4,d6 *adjust for the 4 characters appended
- move.b d6,(a5) *copy adjusted character count to dma
- rts
- nolb: movea.l #tail,a1 *point to user spec with '['
- move.l #6,d2
- jsr movmem *and copy tail to dma
- addi.b #5,d6 *adjust for the 5 characters appended
- move.b d6,(a5) *copy adjusted character count to dma
- finish: rts
- *
- * Parse file name or type, make upper case and expand * to trailing ?'s
- *
- wldfil: move.b (a3),d0
- cmpi.b #'*',d0
- beq qmfill
- subq #1,d2
- bne upper
- rts
- upper: cmpi.b #'a',d0
- blt wldnxt
- andi.b #upmask,d0
- move.b d0,(a3)
- wldnxt: adda #1,a3
- bra wldfil
- qmfill: move.b #'?',(a3)+
- subq #1,d2
- bne qmfill
- rts
- *
- *#######################################################################
- * Time and Date Stamping Subroutines
- *#######################################################################
- *
- * Carry date/time stamp forward for multiple extent file
- *
- carry:
- adda #2,a1 *make a1 point to date stamp
- adda #2,a0 *make a0 point to blank date stamp
- move.l #4,d2 *copy the date stamp
- jsr movmem *from a1 to a0
- rts
- *
- * Check for time and date stamps
- *
- chkstmp:nop
- ifne trs80
- movea.l #trkoff,a0 *determine the directory track
- movea.l #trakno,a1 *number and put it in #trakno
- clr.l d3
- move.w (a0),d3
- move.l d3,(a1)
- jsr strack *position head at the start
- jsr ssector *of the directory track
- jsr dmaset *set dma address
- jsr rsector *and read the first sector
- cmpi.b #1,d0 *any errors?
- bne readok
- movea.l #direrr,a0 *say so and quit on error
- bra erxit
- readok: movea.l #biosdma,a0 *check for stamping marker
- cmpi.b #marker,96(a0) *is directory properly formatted?
- bne noton *if not, date stamping not enabled
- move.b #$20,stampon
- rts
- endc
- noton: move.b #0,stampon
- rts
- *
- * Set dma address for bios calls
- *
- dmaset:
- move.w #calbios,d0
- move.l #dmabpb,d1
- trap #bdos
- rts
- dmabpb: dc.w 12 *set dma address bios parameter block
- dc.l biosdma *use special dma for bios calls
- dc.l 0
- *
- * Read a sector
- *
- rsector:
- move.w #calbios,d0
- move.l #rsbpb,d1
- trap #bdos
- rts
- rsbpb: dc.w 13 *read sector bios parameter block
- dc.l 0
- dc.l 0
- *
- * Set track number
- *
- strack:
- move.w #calbios,d0
- move.l #stbpb,d1
- trap #bdos
- rts
- stbpb: dc.w 10 *set track bios parameter block
- trakno: dc.l 1 *default track = 1
- dc.l 0
- *
- * Set sector number
- *
- ssector:
- move.w #calbios,d0
- move.l #ssbpb,d1
- trap #bdos
- rts
- ssbpb: dc.w 11 *set sector bios parameter block
- sectno: dc.l 0 *default sector = 0
- dc.l 0
- *
- * Display date and time on the console
- *
- display:
- clr.l d6 *put number of days since 1/1/78
- clr.l d7 *into register d7
- movea.l #date1,a1 *point to date
- move.b (a1)+,d6 *low order byte -> d6
- move.b (a1),d7 *high order byte -> d7
- mulu #$100,d7 *multiply by $100
- add.w d6,d7 *d7 now contains 16-bit # of days
- cmpi.w #0,d7 *is the file time/date stamped?
- beq nostamp *no...then display blanks
- jsr year *determine year
- jsr month *determine month
- moveq.l #10,d3 *make base 10 decimal
- move.l d4,d0 *get the month
- jsr prtdec0 *make it decimal and print it
- move.b #'/',d1 *insert a '/'
- jsr type
- move.l d5,d0 *get the day
- jsr prtdec *make it decimal and print it
- move.b #'/',d1 *insert a '/'
- jsr type
- move.l d6,d0 *get the year
- jsr prtdec *make it decimal and print it
- move.b #space,d1 *insert a space
- jsr type
- moveq.l #$10,d3 *make base 10 hexadecimal
- movea.l #hour,a0 *get the hour
- move.b (a0),d0
- jsr prtdec0 *make it decimal and print it
- move.b #':',d1 *insert a ':'
- jsr type
- movea.l #min,a0 *get the minutes
- move.b (a0),d0
- jsr prtdec *make it decimal and print it
- rts
- nostamp:
- movea.l #blnkdt,a0 *print blanks if not time/date stamped
- jsr print
- rts
- *
- * Convert from binary to hexadecimal
- *
- binhex:
- clr.l d2
- divu #$10,d1
- move.w d1,d2
- mulu #10,d2
- clr.w d1
- swap d1
- add.w d2,d1
- rts
- *
- * Convert from hexadecimal to binary
- *
- hexbin:
- clr.l d2
- divu #10,d1
- move.w d1,d2
- mulu #$10,d2
- clr.w d1
- swap d1
- add.w d2,d1
- rts
- *
- * Move today's date from tdate to date1
- *
- loadtd:
- move.l #4,d2
- movea.l #tdate,a1
- movea.l #date1,a0
- jsr movmem
- rts
- *
- * Determine month
- *
- month:
- moveq.l #1,d4 *initialize month register
- move.l d7,d0 *get number of day in current year
- move.l d0,d1
- move.l #feb,a2 *point to number of days in February
- add.w d5,(a2) *adjust for leap year
- move.l #jan,a2 *point to number of days in January
- findmo: sub.w (a2)+,d1
- ble donem *quit if this is the month
- addq #1,d4 *otherwise...increment month number
- move.w d1,d0
- bra findmo *and repeat until month is determined
- donem: move.w d0,d5 *save day of current month in d5
- rts
- *
- * Convert to decimal and display
- *
- prtdec:
- divu d3,d0 *divide by base
- move.w d0,d1 *put tens digit in d1
- swap d0
- move.w d0,d2 *put units digit in d2
- addi.b #48,d1 *make tens digit ascii
- jsr type *and display it
- move.w d2,d1 *get units digit
- addi.b #48,d1 *make it ascii
- jsr type *and display it
- rts
- *
- * Convert to decimal and display, substituting space for
- * leading zero
- *
- prtdec0:
- divu d3,d0 *divide by base
- move.w d0,d1 *put tens digit in d1
- swap d0
- move.w d0,d2 *put units digit in d2
- cmpi.b #0,d1 *is the tens digit zero?
- beq prtspc *yes...print a space
- addi.b #48,d1 *no....make tens digit ascii
- bra cont
- prtspc: move.b #space,d1
- cont: jsr type *and display it
- move.w d2,d1 *get units digit
- addi.b #48,d1 *make it ascii
- jsr type *and display it
- rts
- *
- * Get today's date and time by reading the number of days since
- * January 1, 1978 from the CP/M Plus System Control Block
- *
- today:
- move.l #$daf4,d1 *Z80 address of low order date byte
- jsr readz80 *read it into d1
- movea.l #tdate,a3
- move.b d1,(a3)+ *save it in tdate
- move.l #$daf5,d1 *Z80 address of high order date byte
- jsr readz80 *read it into d1
- move.b d1,(a3)+ *save it in tdate+1
- move.l #$daf6,d1 *Z80 address of hour
- jsr readz80 *read it into d1
- move.b d1,(a3)+ *save it in tdate+2
- move.l #$daf7,d1 *Z80 address of minutes
- jsr readz80 *read it into d1
- move.b d1,(a3) *save it in tdate+3
- clr.l d0 *clean up registers
- clr.l d1
- clr.l a0
- clr.l a1
- rts
- *
- * Read a byte of Z80 memory
- *
- readz80:
- swap d1 *put Z80 address in upper word
- move.w #z80r,d0 *and call special function
- trap #bios *through the BIOS
- rts
- *
- * Determine year
- *
- year:
- clr.l d1
- clr.l d5
- moveq.l #78,d6 *base year is 1978
- move.l d7,d0 *get number of days since 1/1/78
- divu #1461,d0 *home in on 4-year interval (1461 days)
- move.w d0,d1
- mulu #4,d1
- add.w d1,d6 *adjust year for 4-year interval base
- *
- swap d0 *now examine the remainder
- move.w d0,d1
- cmpi.w #0,d1 *see if it's December 31
- bne not1231 *if not...continue
- move.w #365,d0 *if so...adjust
- subq #1,d6
- bra doney
- *
- not1231:subi #365,d1 *subtract 365 days
- ble doney *negative or zero => this is the year
- addq #1,d6 *otherwise add 1 to year
- move.w d1,d0 *save remaining number of days
- *
- subi #365,d1 *subtract another 365 days
- ble doney *negative or zero => this is the year
- addq #1,d6 *otherwise add 1 to year
- move.w d1,d0 *save remaining number of days
- *
- move.b #1,d5 *set the leap-year flag
- subi #366,d1 *subtract 366 days (leap year)
- ble doney *negative or zero => this is the year
- addq #1,d6 *otherwise add 1 to year
- clr.l d5 *reset the leap-year flag
- move.w d1,d0 *save remaining number of days
- *
- doney: move.w d0,d7 *save day of year in d7
- rts
- *#######################################################################
- *
- * End of program code
- *
- * Initialized data area
- *
- even
- jan: dc.w 31
- feb: dc.w 28
- mar: dc.w 31
- apr: dc.w 30
- may: dc.w 31
- jun: dc.w 30
- jul: dc.w 31
- aug: dc.w 31
- sep: dc.w 30
- oct: dc.w 31
- nov: dc.w 30
- dec: dc.w 31
- blnkdt: dc.b ' $'
- direrr: dc.b cr,lf,'Directory Read$'
- dremsg: dc.b cr,lf,'Drive Specification$'
- eosmsg: dc.b ' Press ANY KEY to continue',cr,'$'
- errms1: dc.b space
- errms2: dc.b 'Error$'
- nofms1: dc.b 'No Matching Files on Drive '
- even
- nofms2: dc.b ' : $'
- datmsg: dc.b tab,tab,tab,tab,' Date: $'
- dirms1: dc.b 'Directory for $'
- linmsg: dc.b '----------------------------------------'
- dc.b '---------------------------------------$'
- totms1: dc.b 'Drive $'
- totms2: dc.b ': User $'
- totms3: dc.b ' contains $'
- totms4: dc.b 'k in $'
- totms5: dc.b ' files with $'
- totms6: dc.b 'k free',cr,lf,lf,'$'
- usrmsg: dc.b cr,lf,'User Number$'
- ro: dc.b ' RO'
- rw: dc.b ' RW'
- sys: dc.b ' Sys'
- dir: dc.b ' Dir'
- arc: dc.b ' Arc'
- nonarc: dc.b ' '
- even
- drive: dc.b 0 *drive
- fname: dc.b ' ' *file name
- ftype: dc.b ' ' *file type
- tail: dc.b '[U',0,0,0,0 *dma tail (for user number)
- synerr: dc.b cr,lf,lf,' Syntax Error ','$'
- *
- * Option field lookup table.
- * Note that you can force any of these options as a default by
- * changing the letter for the option into a zero (assuming that
- * its enabling equate is true). Each option that you hard-wire in
- * this manner will no longer be recognized as a command line option,
- * and if you redundantly key it in, SD will flag it as unrecognized.
- *
- otbl equ * *mark start of option table
- ifne aopt *all users-option flag
- aopflg: dc.b 'A'
- endc
- ifne dopt *multi-disk-option flag
- dopflg: dc.b 'D'
- endc
- ifne nopt *no page-pause option flag
- nopflg: dc.b 'N'
- endc
- ifne ropt *unarchived file option flag
- ropflg: dc.b 'R'
- endc
- ifne popt *printer option flag
- popflg: dc.b 'P'
- endc
- ifne sopt *system file option flag
- sopflg: dc.b 'S'
- endc
- oend equ * *mark end of option table
- *
- * End of option lookup table
- *
- even
- lincnt: dc.b 0 *count of lines printed on screen
- fndflg: dc.b 0 *flag whether any files matched
- gotusr dc.b 0
- indent dc.b margsz *size of left margin
- mlps dc.b lps *lines per screen (between pauses)
- mnpl dc.b npl *names per line (# of columns)
- *
- hlpmes: dc.b cr,lf,lf
- dc.b 'Correct usage: SD {d}{u}:{filename.typ} '
- dc.b '[option,option...]'
- dc.b cr,lf,lf,'d = Drive, u = User and filespec are optional'
- dc.b cr,lf,'Wildcards * and ? are supported'
- dc.b cr,lf,lf,'Options available are:',cr,lf
- dc.b cr,lf,tab,'[A]...All users '
- dc.b tab,'[P]...Printed output'
- dc.b cr,lf,tab,'[D]...all Drives'
- dc.b tab,'[R]...unaRchived files'
- dc.b cr,lf,tab,'[N]...No paging '
- dc.b tab,'[S]...System files',cr,lf,lf,'$'
- *
- * Disk parameter block
- *
- even
- cdpb ds.w 1 *number of 128-byte sectors on disk
- blkshf ds.b 1 *Block shift factor..# shifts to mult by sec/blk
- blkmsk ds.b 1 *Block mask...sec/blk - 1
- exmsk ds.b 1 *Extent mask
- res168k ds.b 1 *Reserved byte
- blkmax ds.w 1 *highest block # on drive
- dirmax ds.w 1 *highest file # in directory
- res268k ds.w 1 *Reserved word
- cks ds.w 1 *length of checksum vector
- trkoff ds.w 1 *Track offset to disk directory
- *
- biosdma:ds.b 128
- *
- * Uninitialized data area
- *
- basusr ds.b 1 *dupe of original directory user # to search
- colcnt ds.b 1 *column count
- count ds.w 1 *entry count
- freeby ds.w 1 *contains number of k left on directory drive
- gap ds.w 1 *sort routine storage
- i ds.w 1 *sort routine storage
- j ds.w 1 *sort routine storage
- jg ds.w 1 *sort routine storage
- maxusr ds.b 1 *maximum user # for drive from lookup table
- newusr ds.b 1 *contains user number selected by "U" option
- nextt ds.l 1 *next table entry
- olddsk ds.b 1 *holder for currently logged-in drive
- oldusr ds.b 1 *contains user number upon invocation
- scount ds.w 1 *# to sort
- supspc ds.b 1 *leading space flag for decimal routine
- tbloc ds.l 1 *pointer to start of name table
- tcount ds.w 1 *temporary file count
- temp ds.w 1 *save dir entry
- totfil ds.w 1 *total number of files
- totsiz ds.w 1 *total size of all files
- rorw ds.b 1 *RW/RO flag
- sysdir ds.b 1 *Sys/Dir flag
- arciv ds.b 1 *Archive flag
- stampon ds.b 1 *Date/time stamp flag
- tdflag ds.b 1 *FCB number flag
- tdate ds.b 4 *Today's date and time
- date1 dc.b 0 *1st byte of date from CP/M Plus SCB
- date2 dc.b 0 *2nd byte of date from CP/M Plus SCB
- hour dc.b 0 *hour from CP/M Plus SCB
- min dc.b 0 *minute from CP/M Plus SCB
- leapyr dc.b 0 *leap year flag
- yearda dc.w 0 *number of the day of the year
- extno ds.b 1 *extent number
- sectct ds.b 1 *sector count of last extent
- even
- numrec ds.w 1 *number of records in file
- order equ * *order table starts here
- *#######################################################################
- end