home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
cpm3
/
ts312.aqm
/
TS312.ASM
Wrap
Assembly Source File
|
1985-06-06
|
15KB
|
729 lines
Title 'Time stamp vers: 03.11 date: 10/11/83 time: 22:37:17'
;************************
; *
; timestamp3 *
; *
; version, date & time *
; stamp *
; for cp/m+ *
; *
;************************
; by dick lieber - Bridgeport RCP/M+ (Chicago) 312-326-4392
; based on a program by Eric Forbes
;
; version 3.12 fix leap year bug rcl
; version 3.11 fix wrong data for July & Nov in months table
; version 3.1 don't abort if file not found so a new file
; can be created with editor.
;
; if assembled as a transient program
;
; A>ts3 name.typ [o]
;
; Will increment the minor version number & date/time stamp the file
; name.typ if the strings:
;
; "vers:"
; "time:"
; "date:"
;
; are found in the first 128 bytes of the file. Be sure
; to allow enough blank space after each string for the
; information shown!
;
; [o] is an option:
;
; where o=N to leave old version number
; o=M to increment major version number
; and zero minor version number
;
; if assembled as a patch and SIDed onto an editor
; the same functions will take place automatically
; before the actual edit:
;
; A>edit name.typ [o]
;
; an additional option is added with the patched version:
;
; [z] will cause the timestamp patch to not modify the
; file at all
;
; To attach the patched version of timestamp:
;
; A>mac ts3 <= assemble "patched" version
; CP/M MACRO ASSEM 2.0
; 2B2E
; 024H USE FACTOR
; END OF ASSEMBLY
; A>sid ws.com <= load your editor
; CP/M 3 SID - Version 3.0
; NEXT MSZE PC END
; 2700 2700 0100 CEFF
; #rts3.hex <= load ts3 patch
; NEXT MSZE PC END
; 2B2E 2B2E 0100 CEF <= note the NEXT address
; #wwsts.com,100,2b2e <= save patched editpor
; 0055h record(s) written.
; #^C
; Use and enjoy you new editor that automatically
; updates version etc.
;
maclib z80 ;as supplied with cp/m+
no: equ 0
yes: equ not no
patched: equ yes ;yes to attach to an editor
;no to make transient command
opt$del: equ '[' ;option delimiter
recsiz: equ 128 ;record length
cr: equ 0dh
lf: equ 0ah
bell: equ 7
if patched ;into an editor
;
; these equates define interface of
; this program to the editor
;
; values show are for Wordmaster
endasm: equ 2700h ;where this program will live
oldjmp: equ 269h ;used to restore the jump at the
;start of the assembler
jmpadd: equ 0100h ;address of the JP (C3h) used to get
;to this program
assemb: equ 0100h ;address to return to when finished
;updating the file
;
; this will patch the hook from the editor
; to this porgram. it gets restored automatically
; when when version info has been updated
;
org jmpadd + 1
dw endasm ;patch hook to this program
else
endasm equ 100h ;org if stand alone
fcb equ 5ch ;work at default fcb cause
;we don't care if it's altered
endif
org endasm ;end of assembler or tpa
start: lxi d,crlf
mvi c,prstr ;new line
call bdos
;
; check version
;
mvi c,getvers
call bdos
lxi d,bad$ver$mess
mov a,h
cpi 1 ;check if mp/m
jrz version$ok
mov a,l
cpi 31h
jc exit ;below cp/m+
version$ok:
if patched ;into an editor
;
; copy name to timestamp's fcb
;
lxi h,5ch ;default fcb set up by ccp
lxi d,fcb
lxi b,15 ;length of drive & name
ldir ;move it
endif ;patched
;
; copy password to dma
;
lda 53h ;get password length
ora a ;set flags
jrz no$password
mov c,a ;get length of password
mvi b,0
lhld 51h ;get password address (source)
lxi d,buff ;(dest)
ldir ;move password to dma
;password must be in dma
;on open call if file is
;read protected
no$password:
mvi a,' ' ;no option
sta option
lda 80h ;get command tail length
mov c,a
mvi b,0
lxi h,81h ;start of tail
dad b ;point to end of tail
mvi a,opt$del
ccdr ;search for delimeter
jpo option$done
inx h! inx h ;point to option byte
mov a,m
sta option
cpi 'N' ;keep old version option
jrz option$done
cpi 'M' ;major version update option
jrz option$done
if patched
cpi 'Z' ;no change at all option
mvi a,0 ;no abort
lxi d,as$is$msg
jz exit
endif ;patched
lxi d,bad$opt$msg
mvi a,0ffh ;abort flag
jmp exit
option$done:
;
; open file
;
lxi d,buff
mvi c,setdma
call bdos
lxi d,fcb
mvi c,15
call bdos
lxi d,nofile ;report if can't open and
inr a
if patched
mvi a,0 ;reset abort flag
else
mvi a,0ffh ;set abort flag
endif
jz exit
;
; zero record number
;
lxi h,fcb+33
mvi b,2
rn$loop:
mvi m,0
dcr b
inx h
jrnz rn$loop
lxi d,fcb
mvi c,readran ;read record 1st record (0)
call bdos
lxi d,verstx
call find ;update version
lxi d,novers
cnz print
cz versn
lxi d,datetx
call find ;update date
lxi d,nodate
cnz print
cz date
lxi d,timetx
call find ;update time
lxi d,notime
cnz print
cz time
;
; write record back into file and exit to editor or CP/M
;
mvi c,writeran ;random write
lxi d,fcb
call bdos
mvi c,closef
lxi d,fcb
call bdos
lxi d,done$msg
exit: call print ;print error message and exit.
ora a ;a=ff means abort after message
jnz 0 ;abort if error
if patched ;into editor
;
; Restore the editor to it's original condition and jump to it
;
lxi h,oldjmp ;restore value in hl
shld jmpadd+1 ;restore old jump address
jmp assemb ;jump to the assembler
else
ret ;to cp/m+
endif ;patched
;
; print a string (de) and file name
;
print: push psw
mvi c,prstr
call bdos
lxi h,fcb+1
lxi d,prtnam
lxi b,11
ldir
lxi d,prtfil
mvi c,prstr
call bdos
pop psw
ret
;
;Increment the version number
;
versn: inx h ;hl --> units of major change
lda option ;is a major change requested
cpi 'M'
cz twoinc ;inc major change number
jrz zeromn ;zero minor change number
cpi 'N' ;do not change version if
rz ;'n' option given
inx h
inx h
inx h ;hl --> units of vers no.
twoinc: push psw ;increment a 2 digit field
push h
mvi b,2
mvi a,'9'+1 ;hl --> units position
two1: inr m
cmp m
jrnz twox ;exit if not > 9 ascii
mvi m,'0' ;else zero the units
dcx h ;and inc the tens
djnz two1
twox: pop h
pop psw
ret
zeromn: inx h ;zero minor version
inx h
mvi m,'0' ;used when major changes
inx h
mvi m,'0'
ret
;
; insert new date into buffer at hl
;
date:
call get$clock
push h
lhld datepb ;get days since 1/1/78
call cnvday ;convert to month,day, year
pop h
lda months
call putbcd
mvi m,'/'
inx h
lda days
call putbcd
mvi m,'/'
inx h
lda years
call putbcd
ret
;
; convert bcd in a to two ascii charcters at hl
;
putbcd:
push psw
rrc ! rrc ! rrc ! rrc ;get high nibble
call putnib
pop psw
call putnib
ret
;
; make ascii & put into buffer
;
putnib: ani 0fh
ori '0'
mov m,a
inx h ;next buffer location
ret
;
; insert time into buffer at hl
;
time:
call get$clock
lxi d,datepb+2 ;point to seconds byte
sta datepb+4 ;put seconds in date parm block
mvi b,2
time1: ldax d
inx d
call putbcd ;insert hh:mm:
mvi m,':'
inx h
djnz time1
ldax d
call putbcd ;insert seconds
ret
;
; get time from cp/m+
;
get$clock:
push h
;
; this bios call is needed because the bdos rdtime
; function doesn't call bios to update the clock data
; in the scb
;
mvi c,drbios ;direct bios call
lxi d,biospb ;read time function
call bdos
mvi c,rdtime ;get date/time
lxi d,datepb ;where to put date
call bdos
pop h
ret
biospb: db 26 ;time function
db 0 ;value for A
;
; find the first character of string in de (V, D or T)
;
find: lxi h,buff ;de = compare string
lxi b,recsiz ;limit search to 1 rec
trynxt: ldax d ;get 1st char to find
ccir
rpo ;ret nz set = not found
;
; see if the rest of the string compares equal. Retry
; until we get to the end of the buffer
;
push b
push d
mvi b,5 ;compare next 5 chars
find2: inx d
ldax d
cmp m
jrnz tryagn ;try for another string
inx h
djnz find2 ;keep comparing til b = 0
pop d
pop b
ret ;ret with z set
tryagn: pop d ;Found the 1st character, but
pop b ;there was a bad compare in
jr trynxt ;the next 6 characters.
;************************************************
; *
; cnvdate *
; *
; routine to convert cp/m or mp/m date *
; from days since 1/1/78 to month, day & *
; year. *
; *
; *
;************************************************
;
;
year equ 365 ;leap year gets adjusted for
;
; count up until goal days exceeded
;
cnvday:
shld goaldays ;save as goal to reach
mvi a,1 ;initial values
sta days
sta months ;month counter (jan is one)
lxi h,0
shld dayscnt ;start at zero
lxi d,year ;one year of days
mvi a,78h ;the first year (bcd)
sta years ;save year value
;
; it's much eaiser to detect leap years in binary
;
mvi a,78 ;1st year (binary)
sta years$bin ;for leap year determination
yearloop:
lhld dayscnt
dad d ;trial add one year of days
call ckleap
jrnz no$leap
inx h ;was a leap year
no$leap:
call ckgoal
jnc yeardone ;year over flowed
lda years
cmc ;daa screws up if carry is set
inr a ;add one to the year count
daa ;make bcd
sta years ;save years
jz done ;exact match
shld dayscnt ;year was ok to add
lxi h,years$bin
inr m
jr yearloop
;
yeardone:
;
; see if this is a leap year and adjust Feb if required
;
call ckleap
lxi h,feb ;point to feburary
mvi m,28
jrnz not$leap ;no, don't adjust feb
inr m ;make 29
not$leap:
lxi d,montbl ;point to month table
monthloop:
lhld dayscnt
ldax d ;get month
mov c,a
mvi b,0
dad b
call ckgoal
jnc monthdone
push psw
cmc
lda months
inr a ;count to next month
daa
sta months
pop psw
jrz done ;exact (on the first of the month)
shld dayscnt
inx d ;point to next month
jr monthloop
monthdone:
;
; continue counting until day of month attained
;
lhld dayscnt
daysloop:
inx h ;add one day
call ckgoal
jnc done
cmc ;zero carry bit so daa is screwed up
lda days
inr a
daa
sta days
jr daysloop
done: ret ;leave module
;
; compare count (in hl) with goal
; C if count < goal
; Z if count = goal
;
ckgoal: push d
lded goaldays
mov a,h
cmp d
jrnz ckend
mov a,l
cmp e
ckend: pop d
ret
;
; check for leap year
; return z if leap year
;
ckleap:
lda years$bin ;get years
ani 03h
ret
montbl:
db 31 ;jan
feb: db 28 ;feb
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
; dseg
;
; these values are the output of this module
;
days: ds 1 ;counts days in month (bcd)
months: ds 1 ;counts months in year (bcd)
years: ds 1 ;counts years (starts at 78) (bcd)
;
; cnvdays ram area
;
years$bin: ds 1 ;years in binary (for leap year calc)
dayscnt: ds 2 ;counts days
goaldays: ds 2 ;days since 1/1/78
done$msg:
db 'Version Update$'
nofile: db 'File not found$'
novers: db 'No '
verstx: db 'vers: '
db 'in$'
nodate: db 'No '
datetx: db 'date: '
db 'in$'
notime: db 'No '
timetx: db 'time: '
db 'in$'
crlf: db cr,lf,'$'
if patched ;transient version uses def fcb
fcb: db 0
rept 35
db 0
endm
endif
option: ds 1 ;saved option byte
buff: rept recsiz ;fill with blanks so password
db ' ' ;is set in blanks
endm
prtfil: db ' File:- '
prtnam: db ' ',cr,lf,lf,'$'
datepb: ds 5 ;date parameter block
bad$ver$mess:
db 'Requires CP/M version 3', cr, lf, '$'
bad$opt$msg:
db 'Bad timestamp option.',cr,lf
db 'Options are:',cr,lf
db 9,'[N] for no version update.',cr,lf
db 9,'[M] to increment major version.',cr,lf
if patched
db 9,'[Z] to not alter version or timestamping',cr,lf
endif
db '$'
if patched
as$is$msg:
db 'Version & time unchanged.',cr,lf,'$'
endif
;
; bdos functions (cp/m 3.0)
;
bdos equ 5
sysrst equ 0 ;warmstart
rdcon equ 1 ;wait for & read console character
wrcon equ 2 ;write to console
rdaux equ 3 ;wait for & read aux
wraux equ 4 ;write to aux
list equ 5 ;write to list device
drcon equ 6 ;direct console i/o character or
; ff=read
; fe=status only
; fd=wait for input
auxinst equ 7 ;aux in status
auxotst equ 8 ;aux out status
prstr equ 9 ;de=string
rdbuff equ 10 ;de=buffer max, count, c1,c2,...
const equ 11 ;console in status
getvers equ 12 ;return version in HL
dskrst equ 13 ;reset disk system
seldsk equ 14 ;select disk 0=a:
openf equ 15 ;open file de=fcb
closef equ 16 ;close file
searchf equ 17 ;search for first occurance
searchn equ 18 ;find next occurance
delete equ 19 ;delete file
read equ 20 ;read sequential
write equ 21 ;write sequential
make equ 22 ;make file
rename equ 23 ;rename file new name at fcb+16
loginv equ 24 ;return login vector in hl
curdsk equ 25 ;return current disk in a
setdma equ 26 ;set new dma
getalv equ 27 ;get allocation vector address
wrtprt equ 28 ;write protect current disk
rovec equ 29 ;get r/o vector in hl
setflag equ 30 ;set file attributes
getdpb equ 31 ;return dpb address
user equ 32 ;get/set user ff=get
readran equ 33 ;read random record
writeran equ 34 ;write random record
flsize equ 35 ;compute file size
setran equ 36 ;set random record from last sequential read
rstdrv equ 37 ;reset drive
accdrv equ 38 ;mpm only - access drive
freedrv equ 39 ;mpm only - free drive
wrran0 equ 40 ;fill a random record with 0
tstwrt equ 41 ;mpm only - test and write
lock equ 42 ;mpm only - lock record
unlock equ 43 ;mpm only - unlock record
multi equ 44 ;set multi sector count
errmd equ 45 ;set bdos error mode
freesp equ 46 ;return free space in 1st 3 bytes of dma
chain equ 47 ;chain to pgm name in def buff (80h)
flush equ 48 ;flush buffers
scb equ 49 ;get set scb de=.scb pb db offset
; db ffh set byte
; feh set word
; 00h get
; dw value
drbios equ 50 ;direct bios call de=.bios pb db bios func #
; db = A
; dw =BC
; dw =DE
; dw =HL
ldovl equ 59 ;load overlay
calrsx equ 60 ;call rsx de=.rsx pb db rsx func #
; db # of word parameters
; dw p1
; dw p2
frblks equ 98 ;free temporary blocks
trunf equ 99 ;truncate file
setdirl equ 100 ;set driectory label
dirl equ 101 ;return directory label data e=drive
rdstamp equ 102 ;read file stamps & password mode
wrxfcb equ 103
setdate equ 104
rdtime equ 105
defpwd equ 106 ;set def password
retsn equ 107 ;return serial number address
retcode equ 108 ;get/set return code
conmode equ 109 ;get/set console mode
delim equ 110 ;get/set string output delimiter
prtblk equ 111 ;print block de = ccb dw=address
; dw=length
lstblk equ 112 ;list block
parse equ 152 ;parse file name de=pfcb dw=input addr
; dw=fcb addr
end
length
lstblk equ 112 ;list block
parse equ 152 ;parse file name de=pfcb dw=input a