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
Wrap
Assembly Source File
|
2000-06-30
|
14KB
|
485 lines
; SDATE Version 1.0 -- 11/15/87.
;
; SDATE is intended set the Z80DOS system date on systems that have
; no real time clock. The date is read from the disk label and the
; operater is prompted for changes. Valid replies include "+", "-",
; or a new date. To use: Enter "SDATE" at the CP/M prompt. There
; are no command line options. SDATE.ASM assembles with DRI's ASM.
; - Bill Duerr
;
VER EQU 10 ; Current version number
MO EQU 11 ; Month last modified
DY EQU 15 ; Day
YR EQU 87 ; Year
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
; System equates
;
BDOS EQU 00005
;
CIO EQU 6 ; Console output
RCONS EQU 10 ; Console buffer input
OPEN EQU 15 ; Open file
SRCHF EQU 17 ; Search for First Ambiguous File
SETDAT EQU 104 ; Set Z80DOS date
GETDAT EQU 105 ; Get Z80DOS date
;
FCB1 EQU 5CH
;
TBUF EQU 80H ; Temporary buffer (default) address
;
LF EQU 0AH ; Line feed character
CR EQU 0DH ; Carriage return character
;
; Program starts here
;
ORG 100H
;
START: LXI H,0 ; Make local stack
DAD SP ; Add the address of CCP stack
SHLD STACK ; And save it
LXI SP,STACK ; Set the stack pointer to local stack
;
; Search the directory for the Label file (Format "-ddddddd.vvv")
;
LXI D,FCB1+1 ; Address of default FCB + 1
LXI H,FCB1 ; Start of FCB
MVI M,'?' ; Indicate any file will do
PUSH H ; Save it
MVI B,12 ; Move 12 bytes of the FCB
CALL MOVE ; Propagate "?" through file extent
POP D ; Get back address of default FCB
MVI C,SRCHF ; Get first occurrence of requested file
CALL BDOS
LXI D,NOTFND ; Send warning message
ORA A ; Zero returned for first file in block
JNZ ABEXIT ; Go display message and quit
;
LDA TBUF+1 ; Get the first byte of the first entry
CPI '-' ; Is this a disk label
JNZ ABEXIT ; Go display message and quit
LDA TBUF+96 ; Get the first byte of the last entry
CPI 021H ; Is this a date stamped directory block
JNZ ABEXIT ; Go display message and quit
LDA TBUF+105 ; Get the low order byte of the access date
ORA A ; Is this a valid date
JZ ABEXIT ; Go display message and quit
LXI D,HEADER ; Display program name and header info
CALL DSPMSG
XRA A ; Set end of message
STA TBUF+13 ; After volume number
LXI D,TBUF+9 ; Get address of volume number
CALL DSPMSG
LXI D,COMMA ; Separate volume and description
CALL DSPMSG
XRA A ; Set end of message
STA TBUF+9 ; After disk description
LXI D,TBUF+1 ; Get address of disk description
CALL DSPMSG
;
; Convert a two byte date value in the buffer returned by Search for first
; to binary day of the week
;
DATCHK: LXI D,DATCAP ; Get date caption in DE
CALL DSPMSG ; Display caption
LHLD TBUF+104 ; Number of days since Dec 31, 1977
CHK1: LXI D,-7 ; Number of days in a week
DAD D ; Subtract from our date
JC CHK1 ; Loop till negative
MOV A,L ; Move the complimented day in A
CMA ; Complement it
MVI H,0
MOV L,A ; Get day in HL
LXI B,DAYS ; Point to english day table
DAD B ; Add to find offset into table
MOV L,M ; Get offset
MVI H,0
DAD B ; Point to english day
XCHG ; Get in DE for display routine
CALL DSPMSG ; Display day of week
LXI D,DAYCAP ; Separate day and month
CALL DSPMSG
;
; Convert a two byte date value in the buffer returned by Search for first
; to binary values returned as "date", "month", and "year"
;
LHLD TBUF+104 ; Number of days since Dec 31, 1977
DCX H ; DAD instruction below does not set zero flag
LXI B,0024EH ; Set leap year counter in B, 1978 in C
LXI D,-365 ; Amount to subtract per year
;
CHK2: DAD D ; Subtract 1 year
JNC CHK3 ; Went to far
INR C ; Increment year by one
DCR B ; Decrement leap year counter
JNZ CHK2 ; Not leap year
MVI B,4 ; Every four years it's leap year
DCX H ; Subtract 1 more day for leap year
JMP CHK2 ; Loop till we find our year
;
CHK3: MOV A,C ; Get the calculated year
STA YEAR ; Save calculated binary year
ANI 003H ; Is this a leap year
MVI A,28 ; Show that February has 28 days
JNZ CHK4 ; No, bypass next instructions
INR A ; And each leap year 29
CHK4: STA FEBL ; Save it in the table
LXI B,MONTBL+12 ; Table of number of days/month
MVI D,0 ; Clear D for 16 bit arithmetic
;
CHK5: DCX B ; Move back to the previous month
LDAX B ; Get number of days for this month
MOV E,A ; Put it in DE
DAD D ; Add in month
JNC CHK5 ; Loop till till number of days positive
INX H ; Compensate for DCX above
MOV A,L ; The remainder is the day of month
STA DAY
MOV A,C ; Get the binary value for this month
ANI 00FH ; Save only low order nibble
STA MONTH ; Save for later
;
; Convert the binary values to english words
;
MVI H,0
MOV L,A ; Use month as index into table
DCX H ; Make relative to zero
LXI B,MONTHS ; Point to english month
DAD B ; Find offset into table
MOV L,M
MVI H,0
DAD B ; Point to english month
XCHG ; Get in DE for display routine
CALL DSPMSG ; Display month of year
MVI E,' ' ; Get a space to be displayed
MVI C,CIO ; Console I/O BDOS function
CALL BDOS
LHLD DAY ; Get the day of this month
MVI H,0
CALL DSPDEC ; Display day as a decimal number
LXI D,YCAP ; Get address of separator
CALL DSPMSG ; Display it
LHLD YEAR ; Get the current year
MVI H,0
CALL DSPDEC ; Display year as a decimal number
;
; Ask if any changes are to be made, and get response
;
DATASK: LXI D,ASKCAP ; Get date caption in DE
CALL DSPMSG ; Display caption
MVI A,9 ; Maximum of 8 characters and <CR>
LXI D,BUFFER ; Program's console buffer
STAX D ; Save size of buffer
MVI C,RCONS ; Read Console buffer BDOS function
CALL BDOS
LXI H,BUFFER+1 ; Get number of characters entered
MOV A,M
ORA A ; Where any entered
JZ DONE ; No, set date and return
CPI 1 ; Has just 1 character been entered
JNZ ASK2 ; No, go parse the date
INX H ; Get the first character
MOV A,M
LHLD TBUF+104 ; Number of days since Dec 31, 1977
CPI '+' ; Should we add to the date
JNZ ASK1 ; No
INX H ; Add one to current date
JMP ASK9 ; Go display it and see if any more changes
ASK1: CPI '-' ; Should we subtract from the date
JNZ DATASK ; No, don't know what to do
DCX H ; Subtract one from current date
JMP ASK9 ; Go display new date and see if any more
ASK2: LXI H,BUFFER+2 ; Get address of console input
PUSH H ; Save it
MOV E,A ; Add length to find end of buffer
MVI D,0
DAD D
MOV M,D ; Make sure it's delimited by zero
POP H ; Get address of console input
CALL EDIT ; Edit the month for valid 2 digit number
JZ DATASK ; Didn't pass edit, ask again
CPI 12+1 ; Only 12 months in a year
JNC DATASK ; Ask again
STA MONTH ; Save the month
MOV A,M ; Get next character in console buffer
CPI '/' ; Are we pointing to a "/" separator
JNZ DATASK ; Invalid character, ask again
INX H ; Point to first character of day
CALL EDIT ; Edit it for a valid number
JZ DATASK ; Didn't pass edit, ask again
STA DAY ; Save it
MOV A,M ; Get next character in console buffer
ORA A ; At end of buffer
JZ ASK3 ; Keep the year we had before
CPI '/' ; Are we pointing to a "/" separator
JNZ DATASK ; Invalid character, ask again
INX H ; Point to first character of year
CALL EDIT ; Edit it for a valid number
JZ DATASK ; Didn't pass edit, ask again
STA YEAR ; Save the year
ASK3: LDA YEAR ; Get the year
CPI 80 ; Is year less than 1980
JC DATASK ; Invalid, ask again
CPI 100 ; Is year greater that 1999
JNC DATASK ; Invalid, ask again
PUSH A ; Save the year
ANI 003H ; Is this a leap year
MVI A,28 ; Show that February has 28 days
JNZ ASK4 ; No, bypass next instructions
INR A ; And each leap year 29
ASK4: STA FEBL ; Save it in the table
POP A ; Get back the year
SUI 77 ; Make relative to 1978
MVI B,003H ; Set leap year counter in B
LXI D,365 ; Amount to add per year
LXI H,0 ; Clear H for day counter
;
ASK5: DCR A ; Decrement year by one
JZ ASK6 ; Done calculating number of days so far
DAD D ; Add 1 year
DCR B ; Decrement leap year counter
JNZ ASK5 ; Not leap year
MVI B,4 ; Every four years it's leap year
INX H ; Add 1 more day for leap year
JMP ASK5 ; Loop till we're done
ASK6: PUSH H ; Save number of days beginning of year
LDA MONTH ; Get the month
DCR A ; Make relative to 0
LXI D,MONTBL ; Table of number of days/month
MOV L,A ; Get offset into table for this month
MVI H,0
DAD D ; Point to entry for this month
LDA DAY ; Get the day of the month
DCR A ; Subtract one
CMP M ; Compare to total number of days this month
JNC DATASK ; Invalid day, ask again
XCHG ; Get address of this month in DE
LXI H,0 ; Clear day counter
MOV B,L ; Clear number of day per month area
ASK7: DCX D ; One less month to go
MOV A,E ; Get the low part of table address
ANI 00FH ; Save only the low part
JZ ASK8 ; When zero, we're done
LDAX D ; Get the number of days for this month
MOV C,A ; Get in C to add
DAD B ; Number of days so far this year
JMP ASK7 ; Loop till done
;
ASK8: LDA DAY ; Get the current day
MOV E,A ; Into E for adding
MVI D,0 ; Clear high order
DAD D ; Add to find day of year
POP D ; Get back beginning of year counter
DAD D ; And add it all together
ASK9: SHLD TBUF+104 ; Save it
JMP DATCHK ; Go display it and see if any more changes
;
; End of program
;
DONE: LXI H,0 ; Set time to zero
SHLD TBUF+106 ; In default buffer area
LXI D,TBUF+104 ; Number of days since Dec 31, 1977
MVI C,SETDAT ; Set Date BDOS function
CALL BDOS
LXI D,FCB1 ; Use default FCB
MVI C,OPEN ; Set Date BDOS function
CALL BDOS
;
LXI D,DONEM ; Display "Done"
JMP EXIT
;
; Aborted - display reason
;
ABEXIT: CALL DSPMSG ; Display message pointed to in DE
LXI D,ABORT ; Display "Aborted" message
;
; Exit with message
;
EXIT: CALL DSPMSG ; Display message pointed to by DE
;
; Exit back to the CCP
;
LHLD STACK ; Get original CCP return address
SPHL
RET ; Go back to CCP, no warm boot needed
;
; Edit input for valid one or two digit number
;
EDIT: MOV C,M ; Get a character from memory
MVI B,'0' ; Make tens position a zero
INX H ; Point to next character
MOV A,M ; Get it in A
CMP B ; Check if number
JC EDIT2 ; Not a number, must be units position
MOV B,C ; Move to tens position
MOV C,A ; Move to units position
INX H ; Point to next character in input buffer
EDIT2: MOV A,B
SUI '0' ; Is it a valid number
JC EDIT3
CPI 9+1
JNC EDIT3
MOV B,A ; Save the character
ADD A ; Multiply by 10
ADD A
ADD B
ADD A
MOV B,A ; Save the value
MOV A,C
SUI '0' ; Is it a valid number
JC EDIT3
CPI 9+1
JNC EDIT3
ADD B ; Add in tens position
ORA A ; Set return code to zero
RET
EDIT3: XRA A ; Set return to zero for invalid
RET ; Return to caller
;
; Output zero terminated string pointed to by DE
;
DSPMSG: LDAX D ; Get start of message
ORA A ; At end?
RZ ; Return to caller
PUSH B
PUSH D
PUSH H
MOV E,A ; Get the character to be displayed
MVI C,CIO ; Console I/O BDOS function
CALL BDOS
POP H
POP D
POP B
INX D ; Point to next character
JMP DSPMSG ; Loop till done
;
; Move "B" bytes from "HL" to "DE", Uses A,B,DE,HL
;
MOVE: MOV A,M
STAX D
INX H
INX D
DCR B
JNZ MOVE
RET
;
DSPDEC: MVI D,0 ; Set for leading zero
LXI B,-10
CALL CNVRT ; Convert to decimal
;
MOV A,L ; One's digit was left in L
JMP DSPDGT ; Display the digit and return to caller
;
CNVRT: MVI A,0FFH ; Increments to zero first time used
PUSH H
;
CNVRT1: POP H ; Get the value in HL
PUSH H ; Save as previous value
INR A ; Add one for this position
DAD B ; Subtract power of ten from binary value
XTHL ; Get previous value back
JC CNVRT1 ; Do it until we go negative
POP B ; Get stack right, discard negative value
MVI E,' ' ; Assume the character is a space
ORA D ; Check for leading zeros
JZ DSPSPC ; Return if digit is zero
DSPDGT: MVI D,'0' ; Set D so all zeros will display after this
ORA D ; Convert to ASCII
MOV E,A
DSPSPC: PUSH D
PUSH H
MVI C,CIO ; Console I/O BDOS function
CALL BDOS
POP H
POP D
RET
;
; Program storage area, initialized
;
ABORT: DB CR,LF,'Aborted',0
DONEM: DB CR,LF,'Done',0
NOTFND: DB 'Label Not Found',0
;
DATCAP: DB CR,LF,'Current date set as ',0
ASKCAP: DB CR,LF,'Enter changes or <CR>: ',0
DAYCAP: DB 'day'
COMMA: DB ', ',0
YCAP: DB ', 19',0
;
HEADER: DB 'SDATE Version ',VER / 10 + '0','.',VER MOD 10 + '0',' -- '
DB MO/10+'0',MO MOD 10+'0','/'
DB DY/10+'0',DY MOD 10+'0','/'
DB YR/10+'0',YR MOD 10+'0',CR,LF
DB 'Current disk is volume ',0
MONTHS: DB JAN-MONTHS
DB FEB-MONTHS
DB MAR-MONTHS
DB APR-MONTHS
DB MAY-MONTHS
DB JUN-MONTHS
DB JUL-MONTHS
DB AUG-MONTHS
DB SEP-MONTHS
DB OCT-MONTHS
DB NOV-MONTHS
DB DEC-MONTHS
JAN: DB 'January',0
FEB: DB 'February',0
MAR: DB 'March',0
APR: DB 'April',0
MAY: DB 'May',0
JUN: DB 'June',0
JUL: DB 'July',0
AUG: DB 'August',0
SEP: DB 'September',0
OCT: DB 'October',0
NOV: DB 'November',0
DEC: DB 'December',0
DAYS: DB FRI-DAYS
DB THR-DAYS
DB WED-DAYS
DB TUE-DAYS
DB MON-DAYS
DB SUN-DAYS
DB SAT-DAYS
SUN: DB 'Sun',0
MON: DB 'Mon',0
TUE: DB 'Tues',0
WED: DB 'Wednes',0
THR: DB 'Thurs',0
FRI: DB 'Fri',0
SAT: DB 'Satur',0
;
; Get on 16 byte boundary + 1 (Low order 4 bits is the value of the month)
;
ORG (($+15)/16*16)+1
MONTBL: DB 31 ; Jan
FEBL: DB 28 ; Feb Value stored for leap years
DB 31 ; Mar
DB 30 ; Apr
DB 31 ; May
DB 30 ; Jun
DB 31 ; Jul
DB 31 ; Aug
DB 30 ; Sep
DB 31 ; Oct
DB 30 ; Nov
DB 31 ; Dec
MONTH: DS 1
DAY: DS 1
YEAR: DS 1
;
;
; Storage not initialized by assembler
;
;
DS 64 ; Local stack
ORG ($+255)/256*256 ; Get on page boundary
;
STACK EQU $-2 ; Area for CCP stack pointer
;
BUFFER EQU $ ; Area for console input
END