home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / BDOS / SDATE10.LBR / SDATE10.AZM / SDATE10.ASM
Assembly Source File  |  2000-06-30  |  14KB  |  485 lines

  1. ; SDATE Version 1.0 -- 11/15/87.
  2. ;
  3. ; SDATE is intended set the Z80DOS system date on systems that have
  4. ; no real time clock.  The date is read from the disk label and the
  5. ; operater is prompted for changes.  Valid replies include "+", "-",
  6. ; or a new date.  To use: Enter "SDATE" at the CP/M prompt.  There
  7. ; are no command line options.    SDATE.ASM assembles with DRI's ASM.
  8. ;                - Bill Duerr
  9. ;
  10. VER    EQU    10        ; Current version number
  11. MO    EQU    11        ; Month last modified
  12. DY    EQU    15        ; Day
  13. YR    EQU    87        ; Year
  14. ;
  15. FALSE    EQU    0
  16. TRUE    EQU    NOT FALSE
  17. ;
  18. ; System equates
  19. ;
  20. BDOS    EQU    00005
  21. ;
  22. CIO    EQU    6        ; Console output
  23. RCONS    EQU    10        ; Console buffer input
  24. OPEN    EQU    15        ; Open file
  25. SRCHF    EQU    17        ; Search for First Ambiguous File
  26. SETDAT    EQU    104        ; Set Z80DOS date
  27. GETDAT    EQU    105        ; Get Z80DOS date
  28. ;
  29. FCB1    EQU    5CH
  30. ;
  31. TBUF    EQU    80H        ; Temporary buffer (default) address
  32. ;
  33. LF    EQU    0AH        ; Line feed character
  34. CR    EQU    0DH        ; Carriage return character
  35. ;
  36. ; Program starts here
  37. ;
  38.     ORG    100H
  39. ;
  40. START:    LXI    H,0        ; Make local stack
  41.     DAD    SP        ; Add the address of CCP stack
  42.     SHLD    STACK        ; And save it
  43.     LXI    SP,STACK    ; Set the stack pointer to local stack
  44. ;
  45. ; Search the directory for the Label file (Format "-ddddddd.vvv")
  46. ;
  47.     LXI    D,FCB1+1    ; Address of default FCB + 1
  48.     LXI    H,FCB1        ; Start of FCB
  49.     MVI    M,'?'        ; Indicate any file will do
  50.     PUSH    H        ; Save it
  51.     MVI    B,12        ; Move 12 bytes of the FCB
  52.     CALL    MOVE        ; Propagate "?" through file extent
  53.     POP    D        ; Get back address of default FCB
  54.     MVI    C,SRCHF        ; Get first occurrence of requested file
  55.     CALL    BDOS
  56.     LXI    D,NOTFND    ; Send warning message
  57.     ORA    A        ; Zero returned for first file in block
  58.     JNZ    ABEXIT        ; Go display message and quit
  59. ;
  60.     LDA    TBUF+1        ; Get the first byte of the first entry
  61.     CPI    '-'        ; Is this a disk label
  62.     JNZ    ABEXIT        ; Go display message and quit
  63.     LDA    TBUF+96        ; Get the first byte of the last entry
  64.     CPI    021H        ; Is this a date stamped directory block
  65.     JNZ    ABEXIT        ; Go display message and quit
  66.     LDA    TBUF+105    ; Get the low order byte of the access date
  67.     ORA    A        ; Is this a valid date
  68.     JZ    ABEXIT        ; Go display message and quit
  69.     LXI    D,HEADER    ; Display program name and header info
  70.     CALL    DSPMSG
  71.     XRA    A        ; Set end of message
  72.     STA    TBUF+13        ; After volume number
  73.     LXI    D,TBUF+9    ; Get address of volume number
  74.     CALL    DSPMSG
  75.     LXI    D,COMMA        ; Separate volume and description
  76.     CALL    DSPMSG
  77.     XRA    A        ; Set end of message
  78.     STA    TBUF+9        ; After disk description
  79.     LXI    D,TBUF+1    ; Get address of disk description
  80.     CALL    DSPMSG
  81. ;
  82. ; Convert a two byte date value in the buffer returned by Search for first
  83. ; to binary day of the week
  84. ;
  85. DATCHK:    LXI    D,DATCAP    ; Get date caption in DE
  86.     CALL    DSPMSG        ; Display caption
  87.     LHLD    TBUF+104    ; Number of days since Dec 31, 1977
  88. CHK1:    LXI    D,-7        ; Number of days in a week
  89.     DAD    D        ; Subtract from our date
  90.     JC    CHK1        ; Loop till negative
  91.     MOV    A,L        ; Move the complimented day in A
  92.     CMA            ; Complement it
  93.     MVI    H,0
  94.     MOV    L,A        ; Get day in HL
  95.     LXI    B,DAYS        ; Point to english day table
  96.     DAD    B        ; Add to find offset into table
  97.     MOV    L,M        ; Get offset
  98.     MVI    H,0
  99.     DAD    B        ; Point to english day
  100.     XCHG            ; Get in DE for display routine
  101.     CALL    DSPMSG        ; Display day of week
  102.     LXI    D,DAYCAP    ; Separate day and month
  103.     CALL    DSPMSG
  104. ;
  105. ; Convert a two byte date value in the buffer returned by Search for first
  106. ; to binary values returned as "date", "month", and "year"
  107. ;
  108.     LHLD    TBUF+104    ; Number of days since Dec 31, 1977
  109.     DCX    H        ; DAD instruction below does not set zero flag
  110.     LXI    B,0024EH    ; Set leap year counter in B, 1978 in C
  111.     LXI    D,-365        ; Amount to subtract per year
  112. ;
  113. CHK2:    DAD    D        ; Subtract 1 year
  114.     JNC    CHK3        ; Went to far
  115.     INR    C        ; Increment year by one
  116.     DCR    B        ; Decrement leap year counter
  117.     JNZ    CHK2        ; Not leap year
  118.     MVI    B,4        ; Every four years it's leap year
  119.     DCX    H        ; Subtract 1 more day for leap year
  120.     JMP    CHK2        ; Loop till we find our year
  121. ;
  122. CHK3:    MOV    A,C        ; Get the calculated year
  123.     STA    YEAR        ; Save calculated binary year
  124.     ANI    003H        ; Is this a leap year
  125.     MVI    A,28        ; Show that February has 28 days
  126.     JNZ    CHK4        ; No, bypass next instructions
  127.     INR    A        ; And each leap year 29
  128. CHK4:    STA    FEBL        ; Save it in the table
  129.     LXI    B,MONTBL+12    ; Table of number of days/month
  130.     MVI    D,0        ; Clear D for 16 bit arithmetic
  131. ;
  132. CHK5:    DCX    B        ; Move back to the previous month
  133.     LDAX    B        ; Get number of days for this month
  134.     MOV    E,A        ; Put it in DE
  135.     DAD    D        ; Add in month
  136.     JNC    CHK5        ; Loop till till number of days positive
  137.     INX    H        ; Compensate for DCX above
  138.     MOV    A,L        ; The remainder is the day of month
  139.     STA    DAY
  140.     MOV    A,C        ; Get the binary value for this month
  141.     ANI    00FH        ; Save only low order nibble
  142.     STA    MONTH        ; Save for later
  143. ;
  144. ; Convert the binary values to english words
  145. ;
  146.     MVI    H,0
  147.     MOV    L,A        ; Use month as index into table
  148.     DCX    H        ; Make relative to zero
  149.     LXI    B,MONTHS    ; Point to english month
  150.     DAD    B        ; Find offset into table
  151.     MOV    L,M
  152.     MVI    H,0
  153.     DAD    B        ; Point to english month
  154.     XCHG            ; Get in DE for display routine
  155.     CALL    DSPMSG        ; Display month of year
  156.     MVI    E,' '        ; Get a space to be displayed
  157.     MVI    C,CIO        ; Console I/O BDOS function
  158.     CALL    BDOS
  159.     LHLD    DAY        ; Get the day of this month
  160.     MVI    H,0
  161.     CALL    DSPDEC        ; Display day as a decimal number
  162.     LXI    D,YCAP        ; Get address of separator
  163.     CALL    DSPMSG        ; Display it
  164.     LHLD    YEAR        ; Get the current year
  165.     MVI    H,0
  166.     CALL    DSPDEC        ; Display year as a decimal number
  167. ;
  168. ; Ask if any changes are to be made, and get response
  169. ;
  170. DATASK:    LXI    D,ASKCAP    ; Get date caption in DE
  171.     CALL    DSPMSG        ; Display caption
  172.     MVI    A,9        ; Maximum of 8 characters and <CR>
  173.     LXI    D,BUFFER    ; Program's console buffer
  174.     STAX    D        ; Save size of buffer
  175.     MVI    C,RCONS        ; Read Console buffer BDOS function
  176.     CALL    BDOS
  177.     LXI    H,BUFFER+1    ; Get number of characters entered
  178.     MOV    A,M
  179.     ORA    A        ; Where any entered
  180.     JZ    DONE        ; No, set date and return
  181.     CPI    1        ; Has just 1 character been entered
  182.     JNZ    ASK2        ; No, go parse the date
  183.     INX    H        ; Get the first character
  184.     MOV    A,M
  185.     LHLD    TBUF+104    ; Number of days since Dec 31, 1977
  186.     CPI    '+'        ; Should we add to the date
  187.     JNZ    ASK1        ; No
  188.     INX    H        ; Add one to current date
  189.     JMP    ASK9        ; Go display it and see if any more changes
  190. ASK1:    CPI    '-'        ; Should we subtract from the date
  191.     JNZ    DATASK        ; No, don't know what to do
  192.     DCX    H        ; Subtract one from current date
  193.     JMP    ASK9        ; Go display new date and see if any more
  194. ASK2:    LXI    H,BUFFER+2    ; Get address of console input
  195.     PUSH    H        ; Save it
  196.     MOV    E,A        ; Add length to find end of buffer
  197.     MVI    D,0
  198.     DAD    D
  199.     MOV    M,D        ; Make sure it's delimited by zero
  200.     POP    H        ; Get address of console input
  201.     CALL    EDIT        ; Edit the month for valid 2 digit number
  202.     JZ    DATASK        ; Didn't pass edit, ask again
  203.     CPI    12+1        ; Only 12 months in a year
  204.     JNC    DATASK        ; Ask again
  205.     STA    MONTH        ; Save the month
  206.     MOV    A,M        ; Get next character in console buffer
  207.     CPI    '/'        ; Are we pointing to a "/" separator
  208.     JNZ    DATASK        ; Invalid character, ask again
  209.     INX    H        ; Point to first character of day
  210.     CALL    EDIT        ; Edit it for a valid number
  211.     JZ    DATASK        ; Didn't pass edit, ask again
  212.     STA    DAY        ; Save it
  213.     MOV    A,M        ; Get next character in console buffer
  214.     ORA    A        ; At end of buffer
  215.     JZ    ASK3        ; Keep the year we had before
  216.     CPI    '/'        ; Are we pointing to a "/" separator
  217.     JNZ    DATASK        ; Invalid character, ask again
  218.     INX    H        ; Point to first character of year
  219.     CALL    EDIT        ; Edit it for a valid number
  220.     JZ    DATASK        ; Didn't pass edit, ask again
  221.     STA    YEAR        ; Save the year
  222. ASK3:    LDA    YEAR        ; Get the year
  223.     CPI    80        ; Is year less than 1980
  224.     JC    DATASK        ; Invalid, ask again
  225.     CPI    100        ; Is year greater that 1999
  226.     JNC    DATASK        ; Invalid, ask again
  227.     PUSH    A        ; Save the year
  228.     ANI    003H        ; Is this a leap year
  229.     MVI    A,28        ; Show that February has 28 days
  230.     JNZ    ASK4        ; No, bypass next instructions
  231.     INR    A        ; And each leap year 29
  232. ASK4:    STA    FEBL        ; Save it in the table
  233.     POP    A        ; Get back the year
  234.     SUI    77        ; Make relative to 1978
  235.     MVI    B,003H        ; Set leap year counter in B
  236.     LXI    D,365        ; Amount to add per year
  237.     LXI    H,0        ; Clear H for day counter
  238. ;
  239. ASK5:    DCR    A        ; Decrement year by one
  240.     JZ    ASK6        ; Done calculating number of days so far
  241.     DAD    D        ; Add 1 year
  242.     DCR    B        ; Decrement leap year counter
  243.     JNZ    ASK5        ; Not leap year
  244.     MVI    B,4        ; Every four years it's leap year
  245.     INX    H        ; Add 1 more day for leap year
  246.     JMP    ASK5        ; Loop till we're done
  247. ASK6:    PUSH    H        ; Save number of days beginning of year
  248.     LDA    MONTH        ; Get the month
  249.     DCR    A        ; Make relative to 0
  250.     LXI    D,MONTBL    ; Table of number of days/month
  251.     MOV    L,A        ; Get offset into table for this month
  252.     MVI    H,0
  253.     DAD    D        ; Point to entry for this month
  254.     LDA    DAY        ; Get the day of the month
  255.     DCR    A        ; Subtract one
  256.     CMP    M        ; Compare to total number of days this month
  257.     JNC    DATASK        ; Invalid day, ask again
  258.     XCHG            ; Get address of this month in DE
  259.     LXI    H,0        ; Clear day counter
  260.     MOV    B,L        ; Clear number of day per month area
  261. ASK7:    DCX    D        ; One less month to go
  262.     MOV    A,E        ; Get the low part of table address
  263.     ANI    00FH        ; Save only the low part
  264.     JZ    ASK8        ; When zero, we're done
  265.     LDAX    D        ; Get the number of days for this month
  266.     MOV    C,A        ; Get in C to add
  267.     DAD    B        ; Number of days so far this year
  268.     JMP    ASK7        ; Loop till done
  269. ;
  270. ASK8:    LDA    DAY        ; Get the current day
  271.     MOV    E,A        ; Into E for adding
  272.     MVI    D,0        ; Clear high order
  273.     DAD    D        ; Add to find day of year
  274.     POP    D        ; Get back beginning of year counter
  275.     DAD    D        ; And add it all together
  276. ASK9:    SHLD    TBUF+104    ; Save it
  277.     JMP    DATCHK        ; Go display it and see if any more changes
  278. ;
  279. ; End of program
  280. ;
  281. DONE:    LXI    H,0        ; Set time to zero
  282.     SHLD    TBUF+106    ; In default buffer area
  283.     LXI    D,TBUF+104    ; Number of days since Dec 31, 1977
  284.     MVI    C,SETDAT    ; Set Date BDOS function
  285.     CALL    BDOS
  286.     LXI    D,FCB1        ; Use default FCB
  287.     MVI    C,OPEN        ; Set Date BDOS function
  288.     CALL    BDOS
  289. ;
  290.     LXI    D,DONEM        ; Display "Done"
  291.     JMP    EXIT
  292. ;
  293. ; Aborted - display reason
  294. ;
  295. ABEXIT:    CALL    DSPMSG        ; Display message pointed to in DE
  296.     LXI    D,ABORT        ; Display "Aborted" message
  297. ;
  298. ; Exit with message
  299. ;
  300. EXIT:    CALL    DSPMSG        ; Display message pointed to by DE
  301. ;
  302. ; Exit back to the CCP
  303. ;
  304.     LHLD    STACK        ; Get original CCP return address
  305.     SPHL
  306.     RET            ; Go back to CCP, no warm boot needed
  307. ;
  308. ; Edit input for valid one or two digit number
  309. ;
  310. EDIT:    MOV    C,M        ; Get a character from memory
  311.     MVI    B,'0'        ; Make tens position a zero
  312.     INX    H        ; Point to next character
  313.     MOV    A,M        ; Get it in A
  314.     CMP    B        ; Check if number
  315.     JC    EDIT2        ; Not a number, must be units position
  316.     MOV    B,C        ; Move to tens position
  317.     MOV    C,A        ; Move to units position
  318.     INX    H        ; Point to next character in input buffer
  319. EDIT2:    MOV    A,B
  320.     SUI    '0'        ; Is it a valid number
  321.     JC    EDIT3
  322.     CPI    9+1
  323.     JNC    EDIT3
  324.     MOV    B,A        ; Save the character
  325.     ADD    A        ; Multiply by 10
  326.     ADD    A
  327.     ADD    B
  328.     ADD    A
  329.     MOV    B,A        ; Save the value
  330.     MOV    A,C
  331.     SUI    '0'        ; Is it a valid number
  332.     JC    EDIT3
  333.     CPI    9+1
  334.     JNC    EDIT3
  335.     ADD    B        ; Add in tens position
  336.     ORA    A        ; Set return code to zero
  337.     RET
  338. EDIT3:    XRA    A        ; Set return to zero for invalid
  339.     RET            ; Return to caller
  340. ;
  341. ; Output zero terminated string pointed to by DE
  342. ;
  343. DSPMSG:    LDAX    D        ; Get start of message
  344.     ORA    A        ; At end?
  345.     RZ            ; Return to caller
  346.     PUSH    B
  347.     PUSH    D
  348.     PUSH    H
  349.     MOV    E,A        ; Get the character to be displayed
  350.     MVI    C,CIO        ; Console I/O BDOS function
  351.     CALL    BDOS
  352.     POP    H
  353.     POP    D
  354.     POP    B
  355.     INX    D        ; Point to next character
  356.     JMP    DSPMSG        ; Loop till done
  357. ;
  358. ; Move "B" bytes from "HL" to "DE", Uses A,B,DE,HL
  359. ;
  360. MOVE:    MOV    A,M
  361.     STAX    D
  362.     INX    H
  363.     INX    D
  364.     DCR    B
  365.     JNZ    MOVE
  366.     RET
  367. ;
  368. DSPDEC:    MVI    D,0        ; Set for leading zero
  369.     LXI    B,-10
  370.     CALL    CNVRT        ; Convert to decimal
  371. ;
  372.     MOV    A,L        ; One's digit was left in L
  373.     JMP    DSPDGT        ; Display the digit and return to caller
  374. ;
  375. CNVRT:    MVI    A,0FFH        ; Increments to zero first time used
  376.     PUSH    H
  377. ;
  378. CNVRT1:    POP    H        ; Get the value in HL
  379.     PUSH    H        ; Save as previous value
  380.     INR    A        ; Add one for this position
  381.     DAD    B        ; Subtract power of ten from binary value
  382.     XTHL            ; Get previous value back
  383.     JC    CNVRT1        ; Do it until we go negative
  384.     POP    B        ; Get stack right, discard negative value
  385.     MVI    E,' '        ; Assume the character is a space
  386.     ORA    D        ; Check for leading zeros
  387.     JZ    DSPSPC        ; Return if digit is zero
  388. DSPDGT:    MVI    D,'0'        ; Set D so all zeros will display after this
  389.     ORA    D        ; Convert to ASCII
  390.     MOV    E,A
  391. DSPSPC:    PUSH    D
  392.     PUSH    H
  393.     MVI    C,CIO        ; Console I/O BDOS function
  394.     CALL    BDOS
  395.     POP    H
  396.     POP    D
  397.     RET
  398. ;
  399. ; Program storage area, initialized
  400. ;
  401. ABORT:    DB    CR,LF,'Aborted',0
  402. DONEM:    DB    CR,LF,'Done',0
  403. NOTFND:    DB    'Label Not Found',0
  404. ;
  405. DATCAP:    DB    CR,LF,'Current date set as ',0
  406. ASKCAP:    DB    CR,LF,'Enter changes or <CR>: ',0
  407. DAYCAP:    DB    'day'
  408. COMMA:    DB    ', ',0
  409. YCAP:    DB    ', 19',0
  410. ;
  411. HEADER:    DB    'SDATE Version ',VER / 10 + '0','.',VER    MOD 10 + '0',' -- '
  412.     DB    MO/10+'0',MO MOD 10+'0','/'
  413.     DB    DY/10+'0',DY MOD 10+'0','/'
  414.     DB    YR/10+'0',YR MOD 10+'0',CR,LF
  415.     DB    'Current disk is volume ',0
  416. MONTHS:    DB    JAN-MONTHS
  417.     DB    FEB-MONTHS
  418.     DB    MAR-MONTHS
  419.     DB    APR-MONTHS
  420.     DB    MAY-MONTHS
  421.     DB    JUN-MONTHS
  422.     DB    JUL-MONTHS
  423.     DB    AUG-MONTHS
  424.     DB    SEP-MONTHS
  425.     DB    OCT-MONTHS
  426.     DB    NOV-MONTHS
  427.     DB    DEC-MONTHS
  428. JAN:    DB    'January',0
  429. FEB:    DB    'February',0
  430. MAR:    DB    'March',0
  431. APR:    DB    'April',0
  432. MAY:    DB    'May',0
  433. JUN:    DB    'June',0
  434. JUL:    DB    'July',0
  435. AUG:    DB    'August',0
  436. SEP:    DB    'September',0
  437. OCT:    DB    'October',0
  438. NOV:    DB    'November',0
  439. DEC:    DB    'December',0
  440. DAYS:    DB    FRI-DAYS
  441.     DB    THR-DAYS
  442.     DB    WED-DAYS
  443.     DB    TUE-DAYS
  444.     DB    MON-DAYS
  445.     DB    SUN-DAYS
  446.     DB    SAT-DAYS
  447. SUN:    DB    'Sun',0
  448. MON:    DB    'Mon',0
  449. TUE:    DB    'Tues',0
  450. WED:    DB    'Wednes',0
  451. THR:    DB    'Thurs',0
  452. FRI:    DB    'Fri',0
  453. SAT:    DB    'Satur',0
  454. ;
  455. ; Get on 16 byte boundary + 1 (Low order 4 bits is the value of the month)
  456. ;
  457.     ORG    (($+15)/16*16)+1
  458. MONTBL:    DB    31        ; Jan
  459. FEBL:    DB    28        ; Feb    Value stored for leap years
  460.     DB    31        ; Mar
  461.     DB    30        ; Apr
  462.     DB    31        ; May
  463.     DB    30        ; Jun
  464.     DB    31        ; Jul
  465.     DB    31        ; Aug
  466.     DB    30        ; Sep
  467.     DB    31        ; Oct
  468.     DB    30        ; Nov
  469.     DB    31        ; Dec
  470. MONTH:    DS    1
  471. DAY:    DS    1
  472. YEAR:    DS    1
  473. ;
  474. ;
  475. ; Storage not initialized by assembler
  476. ;
  477. ;
  478.     DS    64        ; Local stack
  479.     ORG    ($+255)/256*256    ; Get on page boundary
  480. ;
  481. STACK    EQU    $-2        ; Area for CCP stack pointer
  482. ;
  483. BUFFER    EQU    $        ; Area for console input
  484.     END
  485.