home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
programs
/
list
/
rap.lbr
/
RAP.AZM
/
RAP.ASM
Wrap
Assembly Source File
|
1989-01-06
|
38KB
|
1,884 lines
;RAP.ASM Reroute all printer data into a diskfile.
;3/07/88
; Copyright 1988, Logic Associates
; 1433 W. Thome, Chicago, IL 60660
;
; Permission is hereby granted only for
; non-profit copying and distribution.
; All other rights reserved.
;
vers equ 10h ;Version 1.0
;
;--------------------------------------------------------
;
; [] For CP/M 2.2. (Not tested with CP/M+.)
;
;==> [] Instructions on re-assembling RAP.ASM are in RAP.DOC.
; PLEASE READ THEM before attempting to re-assemble.
; ------ ---- ----
;
;--------------------------------------------------------
if copy1
*********************************************************
* service/loader routines *
*********************************************************
org 100h
jmp begin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
buffk equ 1 ;printer buffer size in K (1 - 32).
no equ 0
yes equ 255
version db vers
oldver db 0 ;version of already-installed (if any) RAP.
pgplus6 db no ;force load point of module
; to page boundary+6?
loadpnt dw 0 ;entry to module after loading.
xtobdos dw 0 ;RAP exit target.
bdosent dw 0 ;entry point to bdos.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;variables below this point need not be changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;equates
reopen db no ;did log file already exist?
progcode equ 'R' ;code that helps test if RAP already installed.
boot equ 0 ;lowest address within CP/M
bdos equ boot+5 ;bdos jump vector.
fcb equ boot+5ch
filsize equ fcb+33
tbuff equ boot+80h ;default buffer.
fchrn equ 2 ;normal console out.
flist equ 5 ;list to printer.
fchrd equ 6 ;direct console i/o.
pstr equ 9 ;print string.
gvers equ 12 ;get version number.
fdrst equ 13 ;disk reset.
fslct equ 14 ;select disk.
fopen equ 15 ;open file.
fclos equ 16 ;close.
fsrc1 equ 17 ;search first
fsrc2 equ 18 ;search next
fdelt equ 19 ;delete
freds equ 20 ;read seq.
fwseq equ 21 ;write seq.
fmake equ 22 ;create
frenm equ 23 ;rename.
flogv equ 24 ;get login vector.
fgetd equ 25 ;get disk name.
fsdma equ 26 ;set dma
frrov equ 29 ;get r/o vector.
fattr equ 30 ;set file attr.
fuser equ 32 ;set/get user.
frran equ 33 ;read ran.
fwran equ 34 ;write ran.
fsize equ 35 ;compute file size.
fwrnz equ 40 ;write ran with zero fill.
wboff equ 03h ;displacement from bios start to various vecs.
coutoff equ 0ch
lsoff equ 0fh
sdoff equ 24h
dsoff equ 1bh
ctlc equ 3
bell equ 7
bs equ 8
tab equ 9
cr equ 13
lf equ 10
ctlz equ 26
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;messages
eom equ '$'
mlogon db 0,0,0,0,0 ;leave room for "clear screen" string.
db cr,lf
db 'IIIIIIIIII IIIIIII IIIIIIIIII ',cr,lf
db ' IIII IIII IIII III IIII IIII',cr,lf
db ' IIII III IIII III IIII III',cr,lf
db ' IIIIIIIIII IIIIIIIII IIIIIIIII ',cr,lf
db ' IIII III IIII III IIII ',cr,lf
db 'IIIIII IIII IIIII IIIII IIIIII ',cr,lf
db cr,lf
db 'Copyright 1988, Logic Associates, 60660',cr,lf
db eom
mlogon2:
db 'RAP '
verloc:
db 'x.x Installed at '
site1:
db 'xxxx-'
site2:
db 'xxxx',cr,lf
db cr,lf
db 'Reroute/append printer data to a file. ',cr,lf
db cr,lf
db ' * Execute as-- RAP ',cr,lf
db ' or as-- RAP filename ',cr,lf
db cr,lf
db ' * Creates file if absent. ',cr,lf
db cr,lf
db ' * De-installs itself at warmboot. ',cr,lf
db '_______________________________________'
db eom
mnoccp
db cr,lf
db cr,lf
db '** ABORT: Unable to locate CCP. ***'
db bell,cr,lf,eom
mbadcre:
db cr,lf
db cr,lf
db '** ABORT: Cannot create printfile. ***'
db bell,cr,lf,eom
mdifver:
db cr,lf
db cr,lf
db '*** ABORT: RAP versions conflict. ***'
db bell,cr,lf,eom
notinstm:
db cr,lf
db cr,lf
db '** ABORT: Unknown error during install.'
db bell,cr,lf,eom
;db '_______________________________________' ;39 chars.
mstllon:
db bell
db ' already open on '
pdrive1:
db 'A'
punum1:
db '00.*',cr,lf,eom
;db '* File PRINTER.LOG already open on A00.*'
;db '_______________________________________' ;39 chars.
mreopnd:
db ' reopened on '
pdrive2:
db 'A'
punum2:
db '00. *',cr,lf,eom
;db '* File PRINTER.LOG reopened on A00. *'
;db '_______________________________________' ;39 chars.
mopened:
db ' opened on '
pdrive3:
db 'A'
punum3:
db '00. *',cr,lf,eom
;db '* File PRINTER.LOG opened on A00. *'
;db '_______________________________________' ;39 chars.
crlf:
db cr,lf
db eom
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;work areas
bios dw 0 ;pointer to bios.
ccp dw 0 ;pointer to ccp.
;values used in patching traps into bios jumptable.
trapex dw 0
trapent dw 0
biosoff dw 0
deflt db 'PRINTER LOG' ;default print-file name.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; mainline
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
begin lxi h,0
dad sp
shld stack
lxi sp,stack
call hskp ;initialize variables.
jnz beginx ;error-free? no, quit.
lda oldver ;is RAP being installed fresh?
ora a
cz install ; yes, install RAP.
beginx:
call dologon ;display logon message.
lhld stack
sphl
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; housekeeping
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;on exit, if error, z=no, (de)=error message.
hskp:
lxi d,mlogon ;display first part of logon message.
call print
xra a
sta oldver ;clear version number of "old" RAP.
lxi h,0 ;initialize for "CCP not found" msg.
shld loadpnt
lda fcb+1 ;print filename missing?
sui ' '
cz defaultn ; yes, insert default name.
call probe ;if RAP already active?
jz hskp9 ; yes, exit.
lhld boot+1 ;initialize bios pointer.
call isbios ; 14 jmps in a row?
jz hskp4 ; yes, that's bios.
call isxsub ; no, test if XSUB is hiding it.
call isbios
lxi d,mnoccp ;bios found?
jnz hskp9 ; no, abort.
hskp4:
shld bios
call getload ;compute load address, validate if explicit.
; on return, if error, a<>0, z=no.
hskp9:
ret ; if error, z = "no"
;--------------------------------------------------
;instert default name into fcb.
defaultn:
lxi b,11
lxi d,fcb+1
lxi h,deflt
call move
ret
;--------------------------------------------------
;assume xsub is present: get real addr of true coldboot.
;on exit, if yes, hl = address of bios wboot entry.
isxsub:
lhld boot+1
dcx h ; get true warmboot into de,
mov d,m
dcx h
mov e,m
xchg ; then into hl.
ret
;--------------------------------------------------
;test if hl points to bios
isbios dcx h
dcx h
dcx h
push h
lxi d,3 ;test from wboot to write disk.
mvi c,14
isbios2:
dad d
mov a,m
cpi jmp
jz isbios4
cpi ret
mvi a,1
jnz isbios9
isbios4:
dcr c
jnz isbios2
mov a,c
isbios9:
pop h
ret ;if bios, z = yes, a=0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compute load address
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;find bdos, then ccp, then adjust down for length of module.
;on exit, if error, z = no.
getload:
call locbdos ;find bdos.
lxi b,mnoccp
jnz getlod9 ; not found? abort.
call locccp ;find ccp.
lxi b,mnoccp
jnz getlod9 ; not found? abort.
lhld ccp ;point again to start of ccp.
lda bdos+2
sub h ;ccp page < = address-5 page?
jnc getlod1 ; yes, save ccp as tpatop
lhld bdos+1 ; no, save location 5 as tpatop.
getlod1: ;compute load point
lxi d,-modlen
dad d
lda pgplus6
cpi no
jz getlod2
lxi d,-6
dad d
mvi l,6
getlod2:
shld loadpnt ;tentative new loadpnt...
lhld bdos+1 ; and tobdos.
shld xtobdos
xra a ;"no error"
getlod9:
ret ;on exit, z set.
;-------------------------------------------------------
;locate beginning instruction of bdos.
;on exit, if found, z = yes
; hl = bdos start (offset 6)
locbdos:
lhld bios
lxi d,-100h
mvi b,31h ;check for max of 3000h below bios
locbd2:
dcr b
jz locbd6 ;exhausted search, no success: abort.
mvi l,6 ;set for offset to bdos start.
dad d ;compute bdos start
shld bdosent ;save in case found
mov a,m ;is this bdos location?
cpi jmp ;at page plus 6, is there a "jmp"...
jnz locbd2
inx h
mov a,m
cpi 11h
jz locbd4 ; ...followed by an 11h (if CP/M)...
ora a ; ...or a null (if bdos already patched)?
jnz locbd2 ; no, try next lower page in memory.
locbd4:
mvi b,1 ; yes, set to "found"
jmp locbd9
locbd6:
lhld boot+6 ;points to offset 6?
cpi 6
shld bdosent ; yes, assume it's bdos, since
jz locbd4 ; other attempt failed.
locbd9:
dcr b ;set z flag to "yes" (found) or "no" (missing)
mov a,b
ret
;------------------------------------------------
;check for ccp
;on exit, if ccp found, z = yes
; hl = ccpstart
locccp:
lhld bdosent
mvi b,31h ;check no more than 3000h below bdos.
lxi d,-100h
loccp2:
dcr b
jz loccp9
mvi l,0 ;correct to bdos start.
dad d ;advance to next lower page
call isitjmp ;check for two jmp instructions.
jnz loccp2
call isitjmp ;found?
jnz loccp2 ; no, abort.
call isitjmp ;a third found?
jz loccp2 ; yes, abort.
mvi l,0 ;correct to ccp start.
shld ccp
mvi b,1 ;set for "found"
loccp9:
dcr b ;set z flag.
mov a,b
ret
;---------------------------------------------------
;check for jump instruction
isitjmp:
mov a,m
cpi jmp
inx h
inx h
inx h
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; install module
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;move it into place.
;if error, exit with z = no.
install:
call chgaddr ;convert to true addresses.
call customz ;install runtime values.
jnz installx ; exit if error
call doprot ;patch this module in.
call movemod ;move module to load address.
call dopatch ;patch bios for moved module.
call probe ;now detectably installed, as it should be?
jz installx ; yes, exit.
lxi d,notinstm ; no, say "unknown error."
installx:
ret ;if error, a<>0, z=no.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; convert module2 to true addresses ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; change pseudo addresses to true addresses
chgaddr lxi b,loadlen
lxi d,module2
lxi h,module1
truloop ldax d
cmp m
cnz convert
inx h
inx d
dcx b
mov a,b
ora c
jnz truloop
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; convert displacement into address
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
convert push b ;length of module not yet processed
push h ;module1 character position
; get displacement from instruction, put into bc.
ldax d
mov b,a
dcx d
ldax d
mov c,a
lxi h,-module2 ;normalize displacement to zero
dad b
push h
pop b
lhld loadpnt ;add load point for true addr
dad b
; move true address to instruction
mov a,l
stax d
inx d
mov a,h
stax d
pop h
pop b
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; customize module2 at run time
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;on exit, if error, z = no, a<>0.
customz:
lxi h,0
shld fcb+12
shld fcb+14
shld fcb+16
call insertd ;insert drive name into module 2.
call insertu ;insert user number into module 2.
call tryreop ;file already there?
mvi a,yes
jz custmz4 ; yes, skip and say "reopened file."
call trymake ;successful creation of new file?
lxi d,mbadcre
jnz custmzx ; no, abort
mvi a,no ; yes, say "not reopened file."
custmz4:
sta reopen
lxi b,36
lxi d,bfcb+module2 ;copy fcb to trap module.
lxi h,fcb
call move
xra a ;no error
custmzx:
ret ;if error, a<>0, z=no.
;--------------------------------------------------
;insert drive name into module 2.
insertd:
lda fcb
sui 1
mvi c,fgetd ;get curdrv, put into fcb, if
cc bdos ; fcb is asking for default drive.
inr a
sta fcb
adi '@' ;store drive name in module.
sta pdrive1
sta pdrive2
sta pdrive3
sta pdrive+module2
ret
;--------------------------------------------------
;insert user number into module 2.
insertu:
mvi e,255 ;save current user number.
mvi c,fuser ;(= user number for printfile).
call bdos
sta user+module2
mvi b,'0' ;default high-digit of unum.
jmp instu6
instu4:
inr b
instu6:
sui 10 ;unum < 10?
jnc instu4 ; yes, skip
adi 10+'0' ;compute low digit.
mvi h,'.' ;initialize ascii unum,
mov l,a ; in case unum < 10.
mov a,b ;hi digit 0?
cpi '0'
mvi b,' '
jz instu8 ; yes, skip.
mov h,l ; no, put it in front of lo digit.
mov l,a
mvi b,'.'
instu8:
shld punum+module2 ;update module 2.
mov a,b
sta punum+module2+2
shld punum1 ;update messages
shld punum2 ; in loader section.
shld punum3
sta punum1+2
sta punum2+2
sta punum3+2
ret
;--------------------------------------------------
;reuse old log file, if any.
tryreop:
lxi d,fcb ;a successful reopen?
mvi c,fopen
call bdos
ani 0f0h
jnz tryreopx ; no, skip
lxi d,fcb ;address the end of file.
mvi c,fsize
call bdos
lhld filsize ;empty file?
mov a,h
ora l
jz tryreopx ; yes, exit.
dcx h
shld filsize
lxi d,fcb ; no, get last record in file.
mvi c,frran
call bdos
lxi b,80h ;copy it to module2.
lxi d,buffer+module2
lxi h,tbuff
call move
lxi h,buffer+module2 ;adjust buffer pointer
mvi b,0 ; to point to terminal control-Z.
tryreop4:
mov a,m
cpi ctlz ;got it?
jz tryreop8 ; yes, skip.
inx h
inr b
jp tryreop4
mvi m,ctlz ;make up for the missing control-z at end.
tryreop8:
mov l,b ;save the adjusted buffer-char pointer.
mvi h,0
shld bptr+module2
xra a ;"file reopened".
tryreopx:
ret
;--------------------------------------------------
;try to create a new log file.
trymake:
lxi d,fcb
mvi c,fmake
call bdos
ani 0f0h ;successful?
ret ;if yes, a=0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; set all traps ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;set trap for wboot (after module moved into place).
dopatch:
lxi b,trpwbx+1 ;warmboot vector.
lxi d,trpwb
lxi h,wboff
call settrap
lxi b,trpsdx+1 ;set-dma vector.
lxi d,trpsd
lxi h,sdoff
call settrap
lxi b,trplsx+1 ;list vector.
lxi d,trpls
lxi h,lsoff
call settrap
lxi b,trpdsx+1 ;drive select vector.
lxi d,trpds
lxi h,dsoff
call settrap
ret
;--------------------------------------------------------
;set a trap
;on entry, bc=trapex
; de=trapent
; hl=biosoff
settrap:
shld biosoff
xchg
shld trapent
mov h,b
mov l,c
shld trapex
lhld loadpnt ;get address of moved module
push h
pop b ;save in bc
lhld biosoff ;get displace for bios jmptable into de
push h
pop d
;get contents of bios jumptable entry
lhld bios
mvi l,0
dad d ;address bios jumptable entry
inx h
push h ;...save pointer to table entry
mov e,m ;...and get contents
inx h
mov d,m
;store bios entry into trap savearea
lhld trapex ;save bios contents into trap mod
dad b
mov m,e
inx h
mov m,d
;set bios entry to trap entry
lhld trapent ;get addr of appropriate trap into de
dad b
xchg
pop h ;store trap addr in bios jmptab
mov m,e
inx h
mov m,d
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; move module into place
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movemod:
;move module to load point.
lxi b,loadlen+129 ;include potential last record of
lhld loadpnt ; old prinfile + potential ctl-Z.
xchg ;destination.
lxi h,module2 ;source.
call move
ret
;--------------------------------------------------------
;move block: source in hl, destination in de, length in bc.
move0
mov a,m
stax d
inx d
inx h
dcx b
move mov a,b
ora c
jnz move0
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; install security, describe in message
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;move the new secured address to de, then store wherever needed
; secure the module
doprot:
lhld xtobdos
shld tobdos+module2+1
lhld loadpnt
shld bdos+1 ;protect module by altering location 5.
xra a ;say "ok"
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; test if reinstallation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;is RAP already installed?
;on exit, if yes, z = yes,
; loadpnt is updated with addr of loaded module.
probe:
lxi d,0 ;initialize de to 0000.
mvi c,flogv
mvi b,progcode ;ask "RAP recursion?"
call bdos ;"get login vector".
mov a,d ;de still 0000?
ora e ;("RAP uninstalled?")
mvi a,1
jz probe9 ; yes, exit.
xchg
shld loadpnt
mov a,b
sta oldver ;save version number of old RAP.
xra a ;say "already installed"
probe9:
ora a
ret ;if z=yes, RAP installed.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; display messages
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print0:
push d
call charout
pop d
inx d
print:
ldax d
cpi eom
jnz print0
ret
;....................................................
;use direct console out, to allow ctrl-s.
charout: ;display buffer char, save z-flag.
ani 7fh
mov e,a ;display the character.
mvi c,fchrn
call bdos
ret
;....................................................
dologon:
push psw
call parm2m ;insert parmeters into logon message.
lxi d,mlogon2 ;display logon message2.
call print
pop psw ;regular finish?
jz dologon4 ; yes, display rest of normal-end message.
lda oldver ;is this first execution of RAP since w-boot?
ora a
jz dologon9 ; yes, normal error: exit and print err msg.
cpi vers ;old version same as this version?
lxi d,mdifver ; no, say "mismatched versions."
jnz dologon9
lhld loadpnt ;copy current printfile name to default name.
lxi d,bfcb
dad d
lxi d,fcb
lxi b,12
call move
lhld loadpnt ;get unum of active file,
lxi d,punum
dad d
mov e,m
inx h
mov d,m
xchg
shld punum1 ; store it in "still on" message.
inx d
ldax d ;get '.' or ' ',
sta punum1+2 ; store it in "still on" message.
lxi d,mstllon ;say "still on."
jmp dologon6
dologon4:
lda reopen ;display "opened" or "reopened",
cpi yes ; as appropriate.
lxi d,mreopnd
jz dologon6
lxi d,mopened
dologon6:
push d
call dispname ;display filename.
pop d
dologon9:
call print
dologonx:
ret
;---------------------------------------------------------
;display filename from fcb, including a "." if appropriate.
dispname:
lxi d,fileoff+module2
call print
lxi h,fcb+1
mvi b,8
call segout
mov a,m
cpi ' '
jz dispnamx
mvi a,'.'
push h
call charout
pop h
mvi b,3
call segout
dispnamx:
ret
;---------------------------------------------------------
segout:
push h
push b
mov a,m
cpi ' '
cnz charout
pop b
pop h
inx h
dcr b
jnz segout
ret
;---------------------------------------------------------
;insert parms into message.
;install version number.
parm2m:
lhld version
mov a,l
ani 0fh
ori '0' ;build and store lower digit of version number.
sta verloc+2
mvi h,3
dad h
dad h
dad h
dad h
mov a,h ;build and store hi digit of version number.
sta verloc
lhld loadpnt
lxi d,site1 ;loadpoint
call hexinsrt
lhld loadpnt ;endpoint (if loaded)
xchg
lxi h,modlen-1
dad d
mov a,d ;loaded?
ora e
jnz parm2m2 ; yes, skip
lxi h,0 ;set endpoint to 0
parm2m2:
lxi d,site2 ;endpoint
call hexinsrt
ret
;---------------------------------------------------------
hexinsrt:
mov a,h
call nibsert1
mov a,h
call nibsert2
mov a,l
call nibsert1
mov a,l
call nibsert2
ret
nibsert1:
rar
rar
rar
rar
nibsert2:
ani 0fh
adi '0'
cpi '9'+1
jc nibsert3
adi 7
nibsert3:
stax d
inx d
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; stack ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ds 40 ;internal stack area.
stack dw 0 ;savearea for CCP stack pointer.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; end of service routines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
endif
*********************************************************
*********************************************************
* beginning of movable module *
*********************************************************
*********************************************************
org ($+0ffh)/100h*100h ;must be page boundary
adjust set $
if copy1
module1 equ $
endif
if not copy1
module2 equ $
endif
;--------------------------------------------------------
tentry equ $-adjust
jmp trmain+adjust
tobdos equ $-adjust
jmp $-$
db '<RAP >' ;locator for debugging.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; bdos trap ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;beginning of trap module. Uses a max of two levels of
; caller's stack.
trmain equ $-adjust
mov a,c
cpi flogv ;trap login vector.
jz trplog+adjust
cpi fchrn ;trap normal conout.
jz docl+adjust ; (control-P may be active.)
cpi flist ;trap list-to-printer.
jz docl+adjust
cpi pstr ;trap "print-string."
jz dops2+adjust
cpi fsrc1 ;search first?
jz dosrchf+adjust ; yes, go process.
cpi fsrc2 ;search next?
jz dosrchn+adjust ; yes, go process.
jmp tobdos+adjust ; none of the above? exit to bios.
;--------------------------------------------------------------------
;do conout or list.
docl equ $-adjust
lxi h,0 ;save caller's stack,
dad sp ; use local stack.
lxi sp,rstack+adjust
push h
call process+adjust ;output the char.
pop h ;restore caller's stack,
sphl ; then return.
ret
;--------------------------------------------------------------------
;do print-string function.
dops2 equ $-adjust
lxi h,0 ;save caller's stack,
dad sp ; use local stack.
lxi sp,rstack+adjust
push h
jmp dops6+adjust
dops4 equ $-adjust
push d
mvi c,fchrn
mov e,a
call process+adjust ;output the char.
pop d
inx d
dops6 equ $-adjust
ldax d ;all done?
cpi eom
jnz dops4+adjust ; no, loop.
pop h ;restore caller's stack,
sphl ; then return.
ret
;------------------------------------------------------------------
;do "search first".
dosrchf equ $-adjust
xchg
shld oldde+adjust ;save fcb.
xchg
lxi h,0 ;clear "search next" count.
shld srchncnt+adjust
lxi h,nwflush+adjust ;clear "fresh buffer activity" flag.
mvi m,no
call tobdos+adjust ;do the search.
ret ;return with register a intact.
;------------------------------------------------------------------
;do "search next".
dosrchn equ $-adjust
lhld srchncnt+adjust ;update count of "srch next" calls
inx h ;since last "search first".
shld srchncnt+adjust
lda nwflush+adjust ;buffer flushed since latest "search first"?
cpi yes
jnz tobdos+adjust ; no, exit to bios.
lxi h,0 ;save caller's stack,
dad sp ; use local stack.
lxi sp,rstack+adjust
push h
lhld oldde+adjust ;get fcb from latest "search first".
xchg
lhld srchncnt+adjust ;get current count of "srch next" calls
mvi c,fsrc1 ;do one "search first"...
inx h ;(don't count the "search first".)
dosrchn4 equ $-adjust
push h
call tobdos+adjust ;(keep register a intact.)
pop h
mvi c,fsrc2 ; ...and repeat all the "search nexts"s.
dcx h
inr l
dcr l
jnz dosrchn4+adjust
inr h
dcr h
jnz dosrchn4+adjust
lxi h,nwflush+adjust ;clear "fresh buffer activity" flag.
mvi m,no
pop h ;restore caller's stack
sphl
ret ;return with register a intact.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;process character that may go into disk buffer. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
process equ $-adjust
call tobdos+adjust ;output char to console or "list" device.
lda bptr+adjust+1 ;get hi byte of buffer pointer.
cpi bufflen/256 ;buffer full?
cnc wrbuff+adjust ; yes, write out buffer and update
; directory entry.
ret
;----------------------------------------------------------------------------
;write used portion of buffer to disk.
wrbuff equ $-adjust
lda ok+adjust ;disk file still enabled?
cpi yes
jnz wrbuffx+adjust ; no, exit.
mvi c,fuser ;get and save latest user number.
mvi e,255
call tobdos+adjust
sta olduser+adjust
lda user+adjust ;set to printfile's user number.
mov e,a
mvi c,fuser
call tobdos+adjust
lxi h,nwflush+adjust ;set "fresh buffer activity" flag.
mvi m,yes
call testdir+adjust ;is the directory entry still there?
jnz wrbuff9+adjust ; no, exit with printing disabled.
lhld bptr+adjust ;get hi byte of buffer pointer.
mov a,h
cpi bufflen/256 ;buffer full?
jnc wrbuff4+adjust ; yes, convert into records (no incr).
ora l ;buffer empty?
jnz wrbuff2+adjust ; no, increment by one record.
lda buffer+adjust ;is buffer in pristine, unused state?
ora a
jz wrbuff9+adjust ; yes, exit, don't write any records.
wrbuff2 equ $-adjust
lxi d,128 ;"add" one record to buffer.
dad d
wrbuff4 equ $-adjust
mvi a,0
dad h
aci 0
mov b,a
mov c,h ;allows up to a 64K buffer.
wrbuff6 equ $-adjust
push b
lhld dma+adjust ;adjust buffer dma.
xchg
lxi h,128
dad d
shld dma+adjust
mov b,d ;set dma directly to bios,
mov c,e ; bypassing update of "olddma."
call trpsdx+adjust
lxi d,bfcb+adjust ;write a record.
mvi c,fwseq
call tobdos+adjust
pop b
ora a ;error free?
jnz wrbuff8+adjust ; no, abort
dcx b
mov a,b
ora c
jnz wrbuff6+adjust
wrbuff8 equ $-adjust
lxi d,badwmes+adjust
cnz errmess+adjust ;if error, deactivate further printing.
call closeb+adjust ;update disk directory. (ignore error.)
lxi h,0 ;reset buffer char-count.
shld bptr+adjust
lxi h,buffer+adjust ;reset buffer dma.
shld dma+adjust
mvi m,ctlz ;insure initial control-z at buffhead.
lhld olddma+adjust
mov b,h ;restore caller's dma.
mov c,l
call trpsdx+adjust
wrbuff9 equ $-adjust
lda olduser+adjust ;restore caller's user number.
mov e,a
mvi c,fuser
call tobdos+adjust
wrbuffx equ $-adjust
ret
;-----------------------------------------------------------------------
;close buffer
closeb equ $-adjust
lxi d,bfcb+adjust
mvi c,fclos
call tobdos+adjust
push psw
lda bs2+adjust
ori 80h
sta bs2+adjust
pop psw
ret
;-----------------------------------------------------------------------
;test if current directory entry on disk.
;on exit, if error, z = no.
testdir equ $-adjust
mvi b,32 ;copy current fcb to work area.
lxi d,bfcb2+adjust
lxi h,bfcb+adjust
testdr2 equ $-adjust
mov a,m
stax d
inx h
inx d
dcr b
jnz testdr2+adjust
lxi d,bfcb2+adjust ;is file's directory entry on disk?
mvi c,fopen
call tobdos+adjust
ani 0f0h
jnz testd9+adjust ; no, abort.
mvi b,32 ;examine all but drive bytes for exact match.
lxi d,bfcb+adjust
lxi h,bfcb2+adjust
testd2 equ $-adjust
dcr b
jz testd9+adjust
inx h ;(ok to skip compare of the drive bytes.)
inx d
ldax d ;match?
cmp m
jz testd2+adjust ; yes, continue.
testd9 equ $-adjust
lxi d,badmmes+adjust
cnz errmess+adjust
ret
;-----------------------------------------------------------------------
;tell user disk file has been prematurely closed.
errmess equ $-adjust
mvi c,pstr
call tobdos+adjust
lxi d,dablmes+adjust
mvi c,pstr
call tobdos+adjust
mvi a,no
sta ok+adjust
ori 1 ;say "error".
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;trap "get login vector", and make de point to old-RAP entry point.
;(Tells new RAP that old copy is already installed and operating.)
trplog equ $-adjust
mov a,b ; "RAP recursion?"
cpi progcode
jnz tobdos+adjust
call tobdos+adjust
mvi b,vers
lxi d,tentry+adjust ;change to entry addr, to indicate RAP active.
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; bios traps ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;-------------------------------------------------------;
; trap bios warmboot ;
;-------------------------------------------------------;
trpwb equ $-adjust
lxi sp,tbuff+80h
call tstpat+adjust ;patches available for removal?
lxi d,filecon+adjust
jnz trpwb9+adjust ; no, say "file active", try later.
; lda bptr+adjust ;is last record completely filled?
; ani 7fh
; jnz trpwb4+adjust ; no, skip.
;
; lhld bptr+adjust ; yes, make one more record, with ctlz.
; inx h
; shld bptr+adjust
trpwb4 equ $-adjust
call wrbuff+adjust ;flush buffer, update dir, ignore errs.
call remtrps+adjust ;remove all traps.
lxi d,fileoffx+adjust ;say "file closed."
trpwb9 equ $-adjust
call notify+adjust
trpwbx equ $-adjust
jmp $-$
;-----------------------------------------------------------------------
;remove all bios traps.
remtrps equ $-adjust
lhld boot+1
xchg
lhld trpwbx+1+adjust ;unpatch bios warmboot vector.
mvi e,wboff
call unpatch+adjust
lhld trplsx+1+adjust ;unpatch bios list vector.
mvi e,lsoff
call unpatch+adjust
lhld trpsdx+1+adjust ;unpatch bios setdma vector.
mvi e,sdoff ;(do this one last, since it's
call unpatch+adjust ; the one that provides protection.
lhld trpdsx+1+adjust ;unpatch bios drive select.
mvi e,dsoff ;(do this one last, since it's
call unpatch+adjust ; the one that provides protection.
ret
;-----------------------------------------------------------------------
;unpatch bios vector.
unpatch equ $-adjust
xchg
inx h
mov m,e
inx h
mov m,d
xchg
ret
;-----------------------------------------------------------------------
;say "file closed." or "file active."
notify equ $-adjust
push d
lxi d,fileoff+adjust ;output "* File"
mvi c,pstr
call bdos
call nameshow+adjust ;output file name.
pop d ;output "closed on" or "active on"
mvi c,pstr
call bdos
lxi d,pdrive+adjust ;output "on A0."
mvi c,pstr
call bdos
ret
;-----------------------------------------------------------------------
;are patches available for removal?
tstpat equ $-adjust
lhld boot+1 ;make sure warmboot vector has not
xchg ; been repatched by another program.
lxi h,trpwb+adjust
call tstvec+adjust
mvi e,sdoff
lxi h,trpsd+adjust
cz tstvec+adjust
mvi e,lsoff
lxi h,trpls+adjust
cz tstvec+adjust
mvi e,dsoff
lxi h,trpds+adjust
cz tstvec+adjust
ret ;if ok to remove, z = "yes."
;-----------------------------------------------------------------------
;does (de) = hl?
tstvec equ $-adjust
inx d
ldax d ;still intact as we left it?
sub l
mov b,a
inx d
ldax d
sbb h
ora b
ret ; set z = "yes" or "no".
;-------------------------------------------------------;
; trap bios "list output" ;
;-------------------------------------------------------;
;prevent any actual output to printer.
;on exit, bptr points to next empty byte position.
trpls equ $-adjust
lda ok+adjust ;disk file operational?
cpi yes
jnz trpls9+adjust ; no, ignore char.
lhld bptr+adjust
mov a,h
cpi bufflen/256 ;buffer limit reached (full)?
jnc trpls9+adjust ; yes, ignore char.
xchg
lxi h,buffer+adjust ;point to current unused buff-position.
dad d
mov a,c ;if ctl-z, convert to ctl-y.
ani 7fh
cpi ctlz
jnz trpls4+adjust
dcr c
trpls4 equ $-adjust
mov m,c
inx h
mvi m,ctlz ;insure ctlz at end of file.
xchg
inx h
shld bptr+adjust ;point to new unused buff-position.
trpls9 equ $-adjust
ret
;--------------------------------------------------------
;next instruction is used only when unpatching bios.
trplsx equ $-adjust
jmp $-$
;-------------------------------------------------------;
; trap bios setdma ;
;-------------------------------------------------------;
trpsd equ $-adjust
mov h,b
mov l,c
shld olddma+adjust
trpsdx equ $-adjust
call $-$
call reprot+adjust
ret
;--------------------------------------------------------
;reprotect RAP if necessary.
reprot equ $-adjust
lxi d,trmain+adjust ;insure that trap module is protected.
lhld bdos+1
mov a,e
sub l
mov a,d
sbb h
jnc reprotx+adjust
xchg
shld bdos+1
reprotx equ $-adjust
ret
;-------------------------------------------------------;
; trap bios "select drive" ;
;-------------------------------------------------------;
trpds equ $-adjust
trpdsx equ $-adjust
call $-$
push h
call reprot+adjust ;reprotect RAP, if necessary.
pop h
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; conout routines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;display filename from fcb, including a "." if appropriate.
nameshow equ $-adjust
lxi h,bfcb+adjust+1
mvi b,8
call namseg+adjust
mov a,m
cpi ' '
jz nameshwx+adjust
mvi a,'.'
push h
call outchar+adjust
pop h
mvi b,3
call namseg+adjust
nameshwx equ $-adjust
ret
;---------------------------------------------------------
namseg equ $-adjust
push h
push b
mov a,m
cpi ' '
cnz outchar+adjust
pop b
pop h
inx h
dcr b
jnz namseg+adjust
ret
;....................................................
outchar equ $-adjust ;display buffer char, save z-flag.
ani 7fh
mov e,a
mvi c,fchrn
call tobdos+adjust
ret
*********************************************************
*********************************************************
* data areas *
*********************************************************
ok equ $-adjust ;is output file ok?
db yes
dma equ $-adjust
dw buffer+adjust
olddma equ $-adjust ;restore this after writing records to disk.
dw 0
user equ $-adjust
db 0
olduser equ $-adjust ;restore this after writing records to disk.
db 0
nwflush equ $-adjust ;was buffer recently flushed?
db no
srchncnt equ $-adjust ;how many consecutive calls to "search next"?
dw 0
oldde equ $-adjust ;fcb used in latest "search first"
dw 0
;-------------------------------------------------------
badmmes equ $-adjust
db cr,lf,bell
db '>>ERROR: Printfile absent or altered<<',cr,lf,eom
badwmes equ $-adjust
db cr,lf,bell
db '>>ERROR: Printfile disk is full. <<',cr,lf,eom
dablmes equ $-adjust
db '>> Printing is now disabled. <<',cr,lf,eom
fileoff equ $-adjust
db cr,lf
db cr,lf
db '* File '
db eom
;db 'xxxxyyyy.zzz'
fileoffx equ $-adjust
db ' closed on ',eom
pdrive equ $-adjust
db 'A'
punum equ $-adjust
db '00. *',cr,lf,eom
;db '* File PRINTER.LOG closed on A00. *'
;db '_______________________________________',cr,lf
filecon equ $-adjust
db ' active on ',eom
;-------------------------------------------------------
;fcbs
bfcb equ $-adjust ;36 bytes
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0
bs2 equ bfcb+14
brcnt equ bfcb+15
bfcb2 equ $-adjust ;36 bytes
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0
;-------------------------------------------------------
;buffer.
bptr equ $-adjust ;pointer to next empty char in printer buff.
dw 0
loadlen equ $-adjust+1 ;end of initialized ram for RAP module.
buffer equ $-adjust
db 0 ;if null, no printer data yet received.
; ds bufflen ;bufflen+1 leaves room for terminal control-Z.
; ;(adjusted for below).
bufflen equ buffk*1024
buffend equ buffer+bufflen+1
;-------------------------------------------------------
rstack equ buffend+40
modend equ rstack
modlen equ modend+6 ;total length of installed RAP module.
;(extra 6 bytes leaves space for CP/M
; serial #, which may be poked in by EX15.)
*********************************************************
* end of relocatable routines *
*********************************************************
;flip the copy1/copy2 toggle
copy1 set not copy1
;link a second copy, if this was the first copy
if not copy1
link RAP
endif
progend equ $ ;end of assembled program.
end