home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
norge.freeshell.org (192.94.73.8)
/
192.94.73.8.tar
/
192.94.73.8
/
pub
/
computers
/
cpm
/
alphatronic
/
DRIPAK.ZIP
/
CPM_3-0
/
SOURCES
/
GETRSX.ASM
< prev
next >
Wrap
Assembly Source File
|
1982-12-31
|
20KB
|
870 lines
title 'GET.RSX 3.0 - CP/M 3.0 Input Redirection - August 1982'
;******************************************************************
;
; get 'Input Redirection Facility' version 3.0
;
; 11/30/82 - Doug Huskey
; This RSX redirects console input and status from a file.
;******************************************************************
;
;
true equ 0ffffh
false equ 00000h
;
submit equ false ;true if submit RSX
remove$rsx equ false ;true if RSX removes itself
; ;false if LOADER does removes
;
;
; generation procedure
;
; rmac getrsx
; xref getrsx
; link getrsx[op]
; ERA get.RSX
; REN get.RSX=getRSX.PRL
; GENCOM $1.COM get.RSX ($1 is either SUBMIT or GET)
;
;
; initialization procedure
;
; GETF makes a RSX function 60 call with a sub-function of
; 128. GETRSX returns the address of a data table containing:
;
; init$table:
; dw kill ;RSX remove flag addr in GET
; dw bios$constat ;bios entry point in GET
; dw bios$conin ;bios entry point in GET
;
; GETF initializes the data are between movstart: and movend:
; and moves it into GET.RSX. This means that data should not
; be reordered without also changing GETF.ASM.
;
bios$functions equ true ;intercept BIOS console functions
;
; low memory locations
;
wboot equ 0000h
bdos equ 0005h
bdosl equ bdos+1
buf equ 0080h
;
; equates for non graphic characters
;
ctlc equ 03h ; control c
ctle equ 05h ; physical eol
ctlh equ 08h ; backspace
ctlp equ 10h ; prnt toggle
ctlr equ 12h ; repeat line
ctls equ 13h ; stop/start screen
ctlu equ 15h ; line delete
ctlx equ 18h ; =ctl-u
if submit
ctlz equ 0ffh
else
ctlz equ 1ah ; end of file
endif
rubout equ 7fh ; char delete
tab equ 09h ; tab char
cr equ 0dh ; carriage return
lf equ 0ah ; line feed
ctl equ 5eh ; up arrow
;
; BDOS function equates
;
cinf equ 1 ;read character
coutf equ 2 ;output character
crawf equ 6 ;raw console I/O
creadf equ 10 ;read buffer
cstatf equ 11 ;status
pchrf equ 5 ;print character
pbuff equ 9 ;print buffer
openf equ 15 ;open file
closef equ 16 ;close file
delf equ 19 ;delete file
dreadf equ 20 ;disk read
dmaf equ 26 ;set dma function
userf equ 32 ;set/get user number
scbf equ 49 ;set/get system control block word
loadf equ 59 ;loader function call
rsxf equ 60 ;RSX function call
ginitf equ 128 ;GET initialization sub-function no.
gkillf equ 129 ;GET delete sub-function no.
gfcbf equ 130 ;GET file display sub-function no.
pinitf equ 132 ;PUT initialization sub-funct no.
pckillf equ 133 ;PUT CON: delete sub-function no.
pcfcbf equ 134 ;return PUT CON: fcb address
plkillf equ 137 ;PUT LST: delete sub-function no.
plfcbf equ 138 ;return PUT LST:fcb address
gsigf equ 140 ;signal GET without [SYSTEM] option
jinitf equ 141 ;JOURNAL initialization sub-funct no.
jkillf equ 142 ;JOURNAL delete sub-function no.
jfcbf equ 143 ;return JOURNAL fcb address
;
; System Control Block definitions
;
scba equ 03ah ;offset of scbadr from SCB base
ccpflg equ 0b3h ;offset of ccpflags word from page boundary
ccpres equ 020h ;ccp resident flag = bit 5
bdosoff equ 0feh ;offset of BDOS address from page boundary
errflg equ 0ach ;offset of error flag from page boundary
pg$mode equ 0c8h ;offset of page mode byte from pag. bound.
pg$def equ 0c9h ;offset of page mode default from pag. bound.
conmode equ 0cfh ;offset of console mode word from pag. bound.
listcp equ 0d4h ;offset of ^P flag from page boundary
dmaad equ 0d8h ;offset of DMA address from pg bnd.
usrcode equ 0e0h ;offset of user number from pg bnd.
dcnt equ 0e1h ;offset of dcnt, searcha & searchl from pg bnd.
constfx equ 06eh ;offset of constat JMP from page boundary
coninfx equ 074h ;offset of conin JMP from page boundary
;******************************************************************
; RSX HEADER
;******************************************************************
serial: db 0,0,0,0,0,0
trapjmp:
jmp trap ;trap read buff and DMA functions
next: jmp 0 ;go to BDOS
prev: dw bdos
kill: db 0FFh ;0FFh => remove RSX at wstart
nbank: db 0
rname: db 'GET ' ;RSX name
space: dw 0
patch: db 0
;******************************************************************
; START OF CODE
;******************************************************************
;
; ABORT ROUTINE
;
getout:
;
if bios$functions
;
;restore bios jumps
lda restore$mode ;may be FF, 7f, 80 or 0
inr a
rz ; FF = no bios interception
lhld biosin
xchg
lhld biosta
call restore$bios ;restore BIOS constat & conin jmps
rm ; 7f = RESBDOS jmps not changed
lhld scbadr
mvi l,constfx
mvi m,jmp
rpe ; 80 = conin jmp not changed
mvi l,coninfx
mvi m,jmp
endif
ret ; 0 = everything done
;
; ARRIVE HERE ON EACH BIOS CONIN OR CONSTAT CALL
;
;
bios$constat:
;
if bios$functions
;
;enter here from BIOS constat
lxi b,4*256+cstatf ;b=offset in exit table
jmp bios$trap
endif
;
bios$conin:
;
if bios$functions
;
;enter here from BIOS conin
lxi b,6*256+crawf ;b=offset in exit table
mvi e,0fdh
jmp biostrap
endif
;
; ARRIVE HERE AT EACH BDOS CALL
;
trap:
;
;
lxi h,excess
mvi b,0
mov m,b
biostrap:
;enter here on BIOS calls
pop h ;return address
push h ;back to stack
lda trapjmp+2 ;GET.RSX page address
cmp h ;high byte of return address
jc exit ;skip calls on bdos above here
mov a,c ;function number
;
;
cpi cstatf ;status
jz intercept
cpi crawf
jz intercept ;raw I/O
lxi h,statflg ;zero conditional status flag
mvi m,0
cpi cinf
jz intercept ;read character
cpi creadf
jz intercept ;read buffer
cpi rsxf
jz rsxfunc ;rsx function
cpi dmaf
jnz exit ;skip if not setting DMA
xchg
shld udma ;save user's DMA address
xchg
;
exit:
;go to real BDOS
if not bios$functions
;
jmp next ;go to next RSX or BDOS
else
mov a,b ;get type of call:
lxi h,exit$table ;0=BDOS call, 4=BIOS CONIN, 6=BIOS CONSTAT
call addhla
mov b,m ;low byte to b
inx h
mov h,m ;high byte to h
mov l,b ;HL = .exit routine
pchl ;gone to BDOS or BIOS
endif
;
;
rsxfunc: ;check for initialize or delete RSX functions
ldax d ;get RSX sub-function number
lxi h,init$table ;address of area initialized by COM file
cpi ginitf
rz
lda kill
ora a
jnz exit
ldax d
cpi gfcbf
lxi h,subfcb
rz
cksig:
cpi gsigf
jnz ckkill
lxi h,get$active
mvi a,gkillf
sub m ;toggle get$active flag
mov m,a ;gkillf->0 0->gkillf
ckkill:
cpi gkillf ;remove this instance of GET?
jnz exit ;jump if not
restor:
lda get$active
ora a
rz
call getout ;bios jump fixup
if submit
mvi c,closef
call subdos
mvi c,delf
call subdos ;delete SYSIN??.$$$ if not
endif
lxi h,kill
dcr m ;set to 0ffh, so we are removed
xchg ; D = base of this RSX
lhld scbadr
mvi l,ccpflg+1 ;hl = .ccp flag 2 in SCB
mov a,m
ani 0bfh
mov m,a ;turn off redirection flag
;we must remove this RSX if it is the lowest one
lda bdosl+1 ;location 6 high byte
cmp d ;Does location 6 point to us
RNZ ;return if not
if remove$rsx
xchg ;D = scb page
lhld next+1
shld bdosl
xchg ;H = scb page
mvi l,bdosoff ;HL = "BDOS" address in SCB
mov m,e ;put next address into SCB
inx h
mov m,d
xchg
mvi l,0ch ;HL = .previous RSX field in next RSX
mvi m,7
inx h
mvi m,0 ;put previous into previous
ret
else
; CP/M 3 loader does RSX removal if DE=0
mvi c,loadf
lxi d,0
jmp next ;ask loader to remove me
endif
;
;
; INTERCEPT EACH BDOS CONSOLE INPUT FUNCTION CALL HERE
;
; enter with funct in A, info in DE
;
intercept:
;
lda kill
ora a
jnz exit ;skip if remove flag turned on
;
;switch stacks
lxi h,0
dad sp
shld old$stack
lxi sp,stack
push b ;save function #
push d ;save info
;check redirection mode
call getmode ;returns with H=SCB page
cpi 2
jz skip ;skip if no redirection flag on
if submit
;
; SUBMIT PROCESSOR
;
;check if CCP is calling
ckccp: mvi l,pg$mode
mov m,H ;set to non-zero for no paging
mvi l,ccpflg+1 ;CCP FLAG 2 in SCB
mov a,m ;ccp flag byte 2 to A
ori 040h
mov m,a ;set redirection flag on
ani ccpres ;zero flag set if not CCP calling
lda ccp$line
jz not$ccp
;yes, CCP is calling
ora a
jnz redirect ;we have a CCP line
;CCP & not a CCP line
push h
call coninf ;throw away until next CCP line
lxi h,excess
mov a,m
ora a ;is this the first time?
mvi m,true
lxi d,garbage
mvi c,pbuff
cz next ;print the warning if so
pop h
lda kill
ora a
jz ckccp ;get next character (unless eof)
mov a,m
ani 7fh ;turn off disk reset (CCP) flag
mov m,a
jmp wboot ;skip if remove flag turned on
;
not$ccp:
;no, its not the CCP
ora a
jnz skip ;skip if no program line
else
lda program
ora a ;program input only?
mvi l,ccpflg+1 ;CCP FLAG 2 in SCB
mov a,m ;ccp flag byte 2 to A
jz set$no$page ;jump if [system] option
;check if CCP is calling
ani ccpres ;zero flag set if not CCP calling
jz redirect ;jump if not the CCP
lxi h,ccpcnt ;decrement once for each
dcr m ;time CCP active
cm restor ;if 2nd CCP appearance
lxi d,cksig+1
mvi c,rsxf ;terminate any GETs waiting for
call next ;us to finish
jmp skip
;
set$no$page:
ori 40h ;A=ccpflag2, HL=.ccpflag2
mov m,a ;set redirection flag on
mvi l,pg$mode
mov m,h ;set to non-zero for no paging
endif
;
; REDIRECTION PROCESSOR
;
redirect:
;break if control-C typed on console
call break
pop d
pop b ;recover function no. & info
push b ;save function
push d ;save info
mov a,c ;function no. to A
lxi h,retmon ;program return routine
push h ;push on stack
;
;
cpi creadf
jz func10 ;read buffer (returns to retmon)
cpi cinf
jz func1 ;read character (returns to retmon)
cpi cstatf
jz func11 ;status (returns to retmon)
;
func6:
;direct console i/o - read if 0ffh
;returns to retmon
mov a,e
inr a
jz dirinp ;0ffh in E for status/input
inr a
jz CONBRK ;0feh in E for status
lxi h,statflg
mvi m,0
inr a
jz coninf ;0fdh in E for input
;
;direct output function
;
jmp skip1
;
break: ;
;quit if ^C typed
mvi c,cstatf
call real$bdos
ora a ;was ^C typed?
rz
pop h ;throw away return address
call restor ;remove this RSX, if so
mvi c,crawf
mvi e,0ffh
call next ;eat ^C if not nested
;
skip: ;
;reset ^C status mode
call getmode ;returns .conmode+1
dcx h ;hl = .conmode in SCB
mov a,m
ani 0feh ;turn off control C status
mov m,a
;restore the BDOS call
pop d ;restore BDOS function no.
pop b ;restore BDOS parameter
;restore the user's stack
skip1: lhld old$stack
sphl
jmp exit ;goto BDOS
;
retmon:
;normal entry point, char in A
cpi ctlz
jz skip
lhld old$stack
sphl
mov l,a
ret ;to calling program
;******************************************************************
; BIOS FUNCTIONS (REDIRECTION ROUTINES)
;******************************************************************
;
; ;direct console input
dirinp:
call conbrk
ora a
rz
;
;
; get next character from file
;
;
coninf:
getc: ;return ^Z if end of file
xra a
lxi h,cbufp ;cbuf index
inr m ;next chr position
cm readf ;read a new record
ora a
mvi b,ctlz ;EOF indicator
jnz getc1 ;jump if end of file
lda cbufp
lxi h,cbuf
call addhla ;HL = .char
;one character look ahead
;new char in B, current char in nextchr
mov b,m ;new character in B
getc1: mov a,b
cpi ctlz
push b
cz restor
pop b
lxi h,nextchr
mov a,m ;current character
cpi cr
mov m,b ;save next character
rnz
mov a,b ;A=character after CR
cpi lf ;is it a line feed
cz getc ;eat line feeds after a CR
;this must return from above
;rnz because nextchr = lf
;
if submit
;
mov a,b ;get nextchr
sui '<' ;program line?
sta ccp$line ;zero if so
cz getc ;eat '<' char
;this must return from above
;rnz because nextchr = <
endif
mvi a,cr ;get back the cr
ret ;with character in a
;
; set DMA address in DE
;
setdma: mvi c,dmaf
jmp next
;
; read next record
;
readf: mvi c,dreadf ;read next record of input to cbuf
subdos: push b
lxi d,cbuf
call setdma ;set DMA to our buffer
lhld scbadr
lxi d,sav$area ;10 byte save area
pop b ;C = function no.
push h ;save for restore
push d ;save for restore
call mov7 ;save hash info in save area
mvi l,usrcode ;HL = .dcnt in SCB
call mov7 ;save dcnt, searcha & l, user# &
dcx h ;multi-sector I/O count
mvi m,1 ;set multi-sector count = 1
lxi d,subusr ;DE = .submit user #
mvi l,usrcode ;HL = .BDOS user number
ldax d
mov m,a
inx d
call next ;read next record
pop h ;HL = .sav$area
pop d ;DE = .scb
push psw ;save A (non-zero if error)
call mov7 ;restore hash info
mvi e,usrcode ;DE = .dcnt in scb
call mov7 ;restore dcnt search addr & len
lhld udma
xchg
call setdma ;restore DMA to program's buffer
xra a
sta cbufp ;reset buffer position to 0
pop psw
ora a
ret ;zero flag set, if successful
;
; reboot from ^C
;
rebootx:
;store 0fffeh in clp$errcode in SCB
lhld scbadr
mvi l,errflg
mvi m,0feh
inx h
mvi m,0ffh
jmp wboot
;
;
; get input redirection mode to A
; turn on ^C status mode for break
; return .conmode+1 in HL
; preserve registers BC and DE
;
getmode:
lhld scbadr
mvi l,conmode
mov a,m
ori 1 ;turn on ^C status
mov m,a
inx h
mov a,m
ani 3 ;mask off redirection bits
dcr a ;255=false, 0=conditional, 1=true,
ret ; 2=don't redirect input
;
; move routine
;
mov7: mvi b,7
; HL = source
; DE = destination
; B = count
move: mov a,m
stax d
inx h
inx d
dcr b
jnz move
ret
;
; add a to hl
;
addhla: add l
mov l,a
rnc
inr h
ret
;
;******************************************************************
; BDOS CONSOLE INPUT ROUTINES
;******************************************************************
;
; February 3, 1981
;
;
; console handlers
conin: equ coninf
;
conech:
;read character with echo
call conin! call echoc! rc ;echo character?
;character must be echoed before return
push psw! call conout! pop psw
ret ;with character in A
;
echoc:
;are we in cooked or raw mode?
lxi h,cooked! dcr m! inr m! rz ;return if raw
;echo character if graphic
;cr, lf, tab, or backspace
cpi cr! rz ;carriage return?
cpi lf! rz ;line feed?
cpi tab! rz ;tab?
cpi ctlh! rz ;backspace?
cpi ' '! ret ;carry set if not graphic
;
conbrk: ;STATUS - check for character ready
lxi h,statflg
mov b,m! mvi m,0ffh ;set conditional status flag true
call getmode ;check input redirection status mode
cpi 1! rz ;actual status mode => return true
ora a! rz ;false status mode => return false
;conditional status mode => false unless prev func was status
mov a,b! ret ; return false if statflg false
; return true if statflg true
;
;
ctlout:
;send character in A with possible preceding up-arrow
call echoc ;cy if not graphic (or special case)
jnc conout ;skip if graphic, tab, cr, lf, or ctlh
;send preceding up arrow
push psw! mvi a,ctl! call conout ;up arrow
pop psw! ori 40h ;becomes graphic letter
;(drop through to conout)
;
;
; send character in A to console
;
conout:
mov e,a
lda echo
ora a
rz
mvi c,coutf
jmp next
;
;
read: ;read to buffer address (max length, current length, buffer)
xchg ;buffer address to HL
mov c,m! inx h! push h! mvi b,0 ;save .(current length)
;B = current buffer length,
;C = maximum buffer length,
;HL= next to fill - 1
readnx:
;read next character, BC, HL active
push b! push h ;blen, cmax, HL saved
readn0:
call conin ;next char in A
pop h! pop b ;reactivate counters
cpi ctlz! jnz noteof ;end of file?
dcr b! inr b! jz readen ;skip if buffer empty
mvi a,cr ;otherwise return
noteof:
cpi cr! jz readen ;end of line?
cpi lf! jz readen ;also end of line
cpi ctlp! jnz notp ;skip if not ctlp
;list toggle - change parity
push h! push b ;save counters
lhld scbadr! mvi l,listcp ;hl =.listcp
mvi a,1! sub m ;True-listcp
mov m,a ;listcp = not listcp
pop b! pop h! jmp readnx ;for another char
notp:
;not a ctlp
;place into buffer
rdecho:
inx h! mov m,a ;character filled to mem
inr b ;blen = blen + 1
rdech1:
;look for a random control character
push b! push h ;active values saved
call ctlout ;may be up-arrow C
pop h! pop b! mov a,m ;recall char
cpi ctlc ;set flags for reboot test
mov a,b ;move length to A
jnz notc ;skip if not a control c
cpi 1 ;control C, must be length 1
jz rebootx ;reboot if blen = 1
;length not one, so skip reboot
notc:
;not reboot, are we at end of buffer?
cmp c! jc readnx ;go for another if not
readen:
;end of read operation, store blen
pop h! mov m,b ;M(current len) = B
push psw ;may be a ctl-z
mvi a,cr! call conout ;return carriage
pop psw ;restore character
ret
;
func1: equ conech
;return console character with echo
;
;func6: see intercept routine at front of module
;
func10: equ read
;read a buffered console line
;
func11: equ conbrk
;check console status
;
;
;******************************************************************
; DATA AREA
;******************************************************************
statflg: db 0 ;non-zero if prev funct was status
;
;
;******************************************************************
; Following variables and entry points are used by GET.COM
; Their order and contents must not be changed without also
; changing GET.COM.
;******************************************************************
;
if bios$functions
;
exit$table: ;addresses to go to on exit
dw next ;BDOS
endif
;
movstart:
init$table: ;addresses used by GET.COM for
scbadr: dw kill ;address of System Control Block
;
if bios$functions ;GET.RSX initialization
;
biosta dw bios$constat ;set to real BIOS routine
biosin dw bios$conin ;set to real BIOS routine
;
;restore only if changed when removed.
restore$mode
db 0 ;if non-zero change LXI @jmpadr to JMP
;when removed.
restore$bios:
;hl = real constat routine
;de = real conin routine
shld 0 ;address of const jmp initialized by COM
xchg
shld 0 ;address of conin jmp initialized by COM
ret
endif
;
real$bdos:
jmp bdos ;address filled in by COM
;
;
echo: db 1
cooked: db 0
;
program:
db 0 ;true if program input only
subusr: db 0 ;user number for redirection file
subfcb: db 1 ;a:
db 'SYSIN '
db 'SUB'
db 0,0
submod: db 0
subrc: ds 1
ds 16 ;map
subcr: ds 1
;
movend:
;*******************************************************************
cbufp db 128 ;current character position in cbuf
nextchr db cr ;next character (1 char lookahead)
if submit
ccp$line:
db false ;nonzero if line is for CCP
endif
cbuf: ;128 byte record buffer
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
db 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3
udma: dw buf ;user dma address
get$active:
db gkillf
;
sav$area: ;14 byte save area (searchn)
db 68h,68h,68h,68h,68h, 68h,68h,68h,68h,68h
db 68h,68h,68h,68h
excess: db 0
old$stack:
dw 0
if submit
garbage:
; db cr,lf
db 'WARNING: PROGRAM INPUT IGNORED',cr,lf,'$'
else
ccpcnt: db 1
endif
patch$area:
ds 30h
db ' 151282 '
db ' COPYR ''82 DRI '
db 67h,67h,67h,67h,67h, 67h,67h,67h,67h,67h
db 67h,67h,67h,67h,67h, 67h,67h,67h,67h,67h
db 67h,67h,67h,67h,67h, 67h,67h,67h,67h,67h
;
stack: ;15 level stack
end