mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
578 lines
14 KiB
NASM
578 lines
14 KiB
NASM
$title ('PUTF - CP/M 3.0 Output Redirection - August 1982')
|
||
;******************************************************************
|
||
;
|
||
; PUT 'Redirection Initializer' version 3.0
|
||
;
|
||
; 11/30/82 - Doug Huskey
|
||
;******************************************************************
|
||
;
|
||
;
|
||
; Copyright (c) 1982
|
||
; Digital Research
|
||
; P.O. Box 579
|
||
; Pacific Grove, Ca.
|
||
; 93950
|
||
;
|
||
;
|
||
; generation procedure
|
||
;
|
||
; seteof put.plm
|
||
; seteof getscan.dcl
|
||
; seteof putf.asm
|
||
; seteof getscan.plm
|
||
; seteof parse.asm
|
||
; is14
|
||
; asm80 putf.asm debug
|
||
; asm80 mcd80a.asm debug
|
||
; asm80 parse.asm debug
|
||
; plm80 put.plm pagewidth(100) debug optimize
|
||
; link mcd80a.obj,put.obj,parse.obj,putf.obj,plm80.lib to put.mod
|
||
; locate put.mod code(0100H) stacksize(100)
|
||
; era put.mod
|
||
; cpm
|
||
; objcpm put
|
||
; rmac putrsx
|
||
; link putrsx[op]
|
||
; era put.rsx
|
||
; ren put.rsx=putrsx.prl
|
||
; gencom put.com
|
||
; gencom put.com put.rsx
|
||
;
|
||
;
|
||
; This module is called as an external routine by the
|
||
; PL/M program PUT. The address of a the following
|
||
; structure is passed:
|
||
;
|
||
; declare putpb structure
|
||
; (output$type byte,
|
||
; echo$flag byte,
|
||
; filtered$flag byte,
|
||
; system$flag byte);
|
||
;
|
||
; output$type = 0 > console output (default)
|
||
; = 1 > auxiliary output
|
||
; = 2 > list output
|
||
; = 3 > console input
|
||
;
|
||
; echo = true > echo output to real device
|
||
; (default)
|
||
; = false > don't echo output (input is
|
||
; still echoed)
|
||
; filtered = true > convert control characters
|
||
; to a printable form
|
||
; preceeded by an ^
|
||
; = false > no character conversions
|
||
; program = true > continue until user uses
|
||
; PUT command to revert to
|
||
; console
|
||
; = false > active only until program
|
||
; termination
|
||
public putf
|
||
extrn mon1,fcb,memsiz
|
||
;
|
||
;
|
||
true equ 0ffffh
|
||
false equ 00000h
|
||
;
|
||
biosfunctions equ true ;intercept BIOS list or conout
|
||
;
|
||
;
|
||
; low memory locations
|
||
;
|
||
wboot equ 0000h
|
||
wboota equ wboot+1
|
||
;
|
||
; equates for non graphic characters
|
||
;
|
||
cr equ 0dh ; carriage return
|
||
lf equ 0ah ; line feed
|
||
;
|
||
; 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
|
||
lchrf equ 5 ;list character
|
||
pbuff equ 9 ;print buffer
|
||
resetf equ 13 ;disk reset
|
||
selectf equ 14 ;select disk
|
||
openf equ 15 ;open file
|
||
closef equ 16 ;close file
|
||
delf equ 19 ;delete file
|
||
dreadf equ 20 ;disk read
|
||
makef equ 22 ;make file
|
||
dmaf equ 26 ;set dma function
|
||
curdrv equ 25 ;get current drive
|
||
dpbf equ 31 ;get dpb address
|
||
userf equ 32 ;set/get user number
|
||
resdvf equ 37 ;reset drive
|
||
scbf equ 49 ;set/get system control block word
|
||
rsxf equ 60 ;RSX function call
|
||
resalvf equ 99 ;reset allocation vector
|
||
pblkf equ 111 ;print block to console
|
||
lblkf equ 112 ;print block to list device
|
||
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
|
||
jinitf equ 140 ;JOURNAL initialization sub-funct no.
|
||
jkillf equ 141 ;JOURNAL delete sub-function no.
|
||
jfcbf equ 142 ;return JOURNAL fcb address
|
||
skillf equ 144 ;SUBMIT delete sub-function no.
|
||
sfcbf equ 145 ;SUBMIT fcb address function
|
||
svkillf equ 160 ;SAVE delete sub-function no.
|
||
;
|
||
; System Control Block definitions
|
||
;
|
||
scba equ 03ah ;offset of scbadr from SCB base
|
||
ccpflg1 equ 0b3h ;offset of ccpflags word from page boundary
|
||
submit equ 040h ;mask for active submit or get test
|
||
errflg equ 0aah ;offset of error flag from page boundary
|
||
conmode equ 0cfh ;offset of console mode from page boundary
|
||
listcp equ 0d4h ;offset of ^P flag from page boundary
|
||
common equ 0f9h ;offset of common memory base from pg. bound
|
||
wbootfx equ 068h ;offset of warm boot jmp from page. bound
|
||
constfx equ 06eh ;offset of constat jmp from page. bound
|
||
coninfx equ 074h ;offset of conin jmp from page. bound
|
||
conoufx equ 07ah ;offset of conout jmp from page. bound
|
||
listfx equ 080h ;offset of list jmp from page. bound
|
||
cstjmp equ 003h ;offset of console status jmp from warm boot
|
||
cinjmp equ 006h ;offset of console input jmp from warm boot
|
||
coujmp equ 009h ;offset of console output jmp from warm boot
|
||
lstjmp equ 00ch ;offset of list output jmp from warm boot
|
||
|
||
;
|
||
; Restore mode equates (used with inr a, rz, rm, ret)
|
||
;
|
||
norestore equ 0ffh ;no BIOS interception
|
||
biosonly equ 07fh ;restore BIOS jump table only
|
||
everything equ 0 ;restore BIOS jump table and jmps in
|
||
;RESBDOS (default mode)
|
||
;
|
||
; Instructions
|
||
;
|
||
lxih equ 21h ;LXI H, instruction
|
||
jmpi equ 0c3h ;jump instruction
|
||
;
|
||
;******************************************************************
|
||
; START OF INITIALIZATION CODE
|
||
;******************************************************************
|
||
cseg
|
||
|
||
putf:
|
||
;get parameters
|
||
mov h,b
|
||
mov l,c ;HL = .(parameter block)
|
||
mov a,m ;output type 0=con:,1=aux:,2=lst:,3=conin:
|
||
cpi 1 ;is it aux?
|
||
jz notimp ;error if so
|
||
cpi 3 ;is it console input only
|
||
jnz setlst
|
||
sta input ;non-zero => console input
|
||
xra a
|
||
setlst: sta list ;non-zero => list device
|
||
inx h
|
||
mov a,m ;echo/noecho mode
|
||
sta echo
|
||
inx h
|
||
mov a,m ;cooked/raw mode
|
||
sta cooked
|
||
inx h
|
||
mov a,m ;system/program mode
|
||
sta program
|
||
;
|
||
;check if enough memory
|
||
;
|
||
lhld memsiz
|
||
mov a,h
|
||
cpi 20h
|
||
lxi d,memerr
|
||
jc error
|
||
;
|
||
;check if drive specified
|
||
lxi h,fcb
|
||
mov a,m ;drive code
|
||
dcr a ;drive specified?
|
||
jp movfcb ;jump if so
|
||
;
|
||
;set to current drive, if not
|
||
;
|
||
mvi c,curdrv
|
||
push h ;save .fcb
|
||
call mon1
|
||
pop h ;a=current drive, hl=.fcb
|
||
mov m,a ;set fcb to force drive select
|
||
inr m ;must be relative to 1
|
||
;
|
||
movfcb: ;copy default fcb up into data area for move to RSX
|
||
;
|
||
mov e,a
|
||
mvi c,selectf ;make sure drive is selected
|
||
push h ;save .fcb
|
||
call mon1 ;so we get the right DPB
|
||
pop h
|
||
lxi d,putfcb
|
||
lxi b,32 ;length of fcb
|
||
call ldir ;move it to putfcb
|
||
;
|
||
;initialize other variables to be moved to RSX
|
||
;
|
||
call getusr ;get current user number
|
||
sta putusr ;save for redirection file I/O
|
||
call getscbadr
|
||
shld scbadr ;System Control Block address
|
||
;
|
||
;initialize records per block (BLM)
|
||
;
|
||
mvi c,dpbf
|
||
call mon1 ;HL = .disk parameter block
|
||
inx h
|
||
inx h
|
||
inx h ;HL = .blm
|
||
mov a,m
|
||
sta blm
|
||
;
|
||
;initialize function table (functions to be intercepted)
|
||
;
|
||
lda list
|
||
ora a
|
||
lxi b,funcend-functbl ;count
|
||
lxi d,functbl ;destination
|
||
lxi h,pcfcbf*256+pckillf ;rsx function codes
|
||
jz ckinput
|
||
lxi h,listfunc ;list function table
|
||
call ldir
|
||
mvi a,lchrf
|
||
sta bdosfunc ;use list output for bios trap
|
||
mvi a,listfx
|
||
sta resoff ;offset of fixup for bios list
|
||
mvi a,lstjmp
|
||
sta biosoff ;offset of bios lst jmp
|
||
lxi h,plfcbf*256+plkillf
|
||
jmp getrsxadr
|
||
ckinput:
|
||
lda input
|
||
ora a
|
||
jz getrsxadr
|
||
lxi h,inputfunc
|
||
call ldir
|
||
mvi a,cinf
|
||
sta bdosfunc ;use console input
|
||
mvi a,coninfx
|
||
sta resoff ;offset of fixup for bios conin
|
||
mvi a,cinjmp
|
||
sta biosoff
|
||
sta echo ;must be non-zero for input
|
||
lhld scbadr
|
||
mvi l,ccpflg+1
|
||
mov a,m
|
||
ani submit ;SUBMIT or GET active?
|
||
lxi d,noget
|
||
jnz error ;error if so
|
||
lxi h,jfcbf*256+jkillf
|
||
;
|
||
;get address of initialization table in RSX
|
||
;
|
||
getrsxadr:
|
||
shld rsxfun
|
||
mvi c,rsxf ;PUT is not compatible with SAVE.RSX
|
||
lxi d,savkill ;as both SAVE & PUT trap warm starts
|
||
call mon1 ;eliminate SAVE.RSX if active
|
||
mvi c,rsxf
|
||
lxi d,rsxinit
|
||
call mon1 ;call PUT.RSX initialization routine
|
||
push h ;save address of destination for move
|
||
mov e,m
|
||
inx h
|
||
mov d,m ;DE = .kill flag
|
||
push d ;save for later set
|
||
;
|
||
if biosfunctions
|
||
;
|
||
inx h
|
||
inx h
|
||
inx h ;HL = .(.(bios entry in RSX))
|
||
push h ;save for getting RSX entry point
|
||
;later (in trap:)
|
||
;check if BIOS jump table looks valid (jmp in right places)
|
||
check: lhld biosoff
|
||
xchg
|
||
lhld wboota
|
||
mov a,m
|
||
cpi jmpi ;should be a jump
|
||
dad d ;HL = .(jmp address)
|
||
mov a,m
|
||
cpi jmpi ;should be a jump
|
||
jnz bioserr ;skip bios redirection if not
|
||
;
|
||
;fix up RESBDOS to do BIOS calls to intercepted functions
|
||
;
|
||
lhld scbadr
|
||
mvi l,common+1
|
||
mov a,m ;get high byte of common base
|
||
ora a
|
||
jnz fix0 ;high byte = zero if non-banked
|
||
mvi a,biosonly
|
||
sta biosmode
|
||
jmp trap ;skip code that fixes resbdos
|
||
;fix warmboot BIOS jmp in resbdos
|
||
fix0: mvi l,wbootfx ;HL = .warm boot fix in SCB
|
||
shld wmfix ;save for RSX restore at end
|
||
mov a,m
|
||
cpi jmpi ;is it a jump instruction?
|
||
jz fix1 ;jump if so
|
||
mvi a,biosonly ;whoops already traped
|
||
sta biosmode
|
||
fix1: mvi m,lxih ;change jump to an lxi h,
|
||
;fix list bios jmp in resbdos
|
||
lda resoff
|
||
mov l,a
|
||
shld biosfix
|
||
mov a,m
|
||
cpi jmpi ;is it a jump instruction?
|
||
jz biosck ;jump if so
|
||
mvi a,biosonly ;whoops already changed
|
||
sta biosmode ;restore jump table only
|
||
fix3: mvi m,lxih
|
||
;
|
||
;get address of list entry point
|
||
;
|
||
trap: pop h ;.(.(bios entry point in RSX))
|
||
mov c,m
|
||
inx h
|
||
mov b,m
|
||
push h
|
||
lhld biosoff
|
||
xchg
|
||
lhld wboota
|
||
dad d ;HL = .(jmp address)
|
||
inx h ;move past jmp instruction
|
||
shld biosjmp ;save for RSX restore at end
|
||
mov e,m
|
||
mov m,c
|
||
inx h
|
||
mov d,m ;DE = bios routine address
|
||
mov m,b ;BIOS jmp jumps to RSX
|
||
xchg
|
||
shld biosout ;save bios routine address
|
||
;get addresses of RSX bios trap
|
||
pop h
|
||
inx h
|
||
mov c,m ;HL = .(.(bios warm start in RSX))
|
||
inx h
|
||
mov b,m ;BC = .bios warmstart entry in RSX
|
||
;
|
||
;patch RSX wmboot entry into BIOS jump table
|
||
;save real wmboot address in RSX exit table
|
||
;
|
||
lhld wboota
|
||
inx h
|
||
shld wmjmp ;save for RSX restore at end
|
||
mov e,m
|
||
mov m,c
|
||
inx h
|
||
mov d,m
|
||
mov m,b
|
||
xchg
|
||
shld wmsta ;save real bios warm start routine
|
||
endif
|
||
;
|
||
;move data area to RSX
|
||
;
|
||
rsxmov:
|
||
pop h ;HL = .(kill flag = 0FFh)
|
||
inr m ;set to zero for redirection active
|
||
lxi h,movstart
|
||
pop d ;RSX data area address
|
||
lxi b,movend-movstart
|
||
call ldir
|
||
jmp wboot
|
||
;
|
||
; auxiliary redirection
|
||
;
|
||
notimp:
|
||
lxi d,notdone
|
||
error:
|
||
mvi c,pbuff
|
||
call mon1
|
||
mvi c,closef
|
||
lxi d,fcb
|
||
call mon1
|
||
mvi c,delf
|
||
lxi d,fcb
|
||
call mon1
|
||
jmp wboot
|
||
|
||
|
||
if biosfunctions
|
||
;
|
||
; check if warm boot was fixed up by someone
|
||
; and list or console output was not
|
||
;
|
||
biosck: lda biosmode
|
||
cpi biosonly
|
||
jnz fix3 ;warm boot not fixed up
|
||
;
|
||
; can't do BIOS redirection
|
||
;
|
||
bioserr:
|
||
lxi d,nobios
|
||
mvi c,pbuff
|
||
call mon1
|
||
lxi h,biosmode
|
||
mvi m,norestore
|
||
pop h ;throw away stacked bios entry
|
||
jmp rsxmov
|
||
endif
|
||
;
|
||
; get/set user number
|
||
;
|
||
getusr: mvi a,0ffh ;get current user number
|
||
setusr: mov e,a ;set current user number (in A)
|
||
mvi c,userf
|
||
jmp mon1
|
||
;
|
||
; get system control block address
|
||
; (BDOS function #49)
|
||
;
|
||
; exit: hl = system control block address
|
||
;
|
||
getscbadr:
|
||
mvi c,scbf
|
||
lxi d,data49
|
||
jmp mon1
|
||
;
|
||
data49: db scba,0 ;data structure for getscbadd
|
||
;
|
||
;
|
||
; copy memory bytes (emulates z80 ldir instruction)
|
||
;
|
||
ldir: mov a,m ;get byte
|
||
stax d ;store it at destination
|
||
inx h ;advance pointers
|
||
inx d
|
||
dcx b ;decrement byte count
|
||
mov a,c ;loop if non-zero
|
||
ora b
|
||
jnz ldir
|
||
ret
|
||
;
|
||
;******************************************************************
|
||
; DATA AREA
|
||
;******************************************************************
|
||
|
||
;
|
||
; equates function table
|
||
;
|
||
eot equ 0ffh ; end of function table
|
||
skipf equ 0feh ; skip this function
|
||
;
|
||
listfunc:
|
||
db lchrf, lblkf, coutf, cstatf, crawf
|
||
db pbuff, cinf, creadf, resetf, resdvf
|
||
db resalvf, pblkf, eot
|
||
|
||
; Note that the list routines precede the console
|
||
; routines so that the CKLIST: routine in PUTRSX
|
||
; can distinquish list functions from console
|
||
; functions.
|
||
|
||
inputfunc: ;preset for console input
|
||
db skipf, skipf, skipf, skipf, crawf
|
||
db skipf, cinf, creadf, resetf, resdvf
|
||
db resalvf, eot, skipf
|
||
|
||
|
||
;
|
||
savkill: db svkillf
|
||
rsxinit: db Pinitf
|
||
nobios: db cr,lf,'WARNING: Cannot redirect from BIOS',cr,lf,'$'
|
||
notdone:
|
||
db cr,lf
|
||
db 'ERROR: Auxiliary device redirection not implemented',cr,lf,'$'
|
||
memerr:
|
||
db cr,lf
|
||
db 'ERROR: Insufficient Memory',cr,lf,'$'
|
||
noget:
|
||
db cr,lf
|
||
db 'ERROR: You cannot PUT INPUT to a file',cr,lf
|
||
db ' when using GET or SUBMIT.',cr,lf,'$'
|
||
resoff: db conoufx
|
||
biosoff: dw coujmp
|
||
aux: db 0
|
||
;
|
||
;******************************************************************
|
||
; Following variables are initialized by PUT.COM
|
||
; and moved to the PUT RSX - Their order must not be changed
|
||
;******************************************************************
|
||
;
|
||
;
|
||
movstart:
|
||
inittable: ;addresses used by PUT.COM for
|
||
scbadr: dw 0 ;address of System Control Block
|
||
;
|
||
if biosfunctions ;PUT.RSX initialization
|
||
;
|
||
gobios: mov c,e
|
||
db jmpi
|
||
biosout:
|
||
dw 0 ;set to real BIOS routine
|
||
;
|
||
;restore only if changed when removed.
|
||
biosjmp:
|
||
dw 0 ;address of bios jmp initialized by COM
|
||
biosfix:
|
||
dw 0 ;address of jmp in resbdos to restore
|
||
db jmpi
|
||
wmsta: dw 0 ;address of real warm start routine
|
||
wmjmp: dw 0 ;address of jmp in bios to restore
|
||
wmfix: dw 0 ;address of jmp in resbdos to restore
|
||
bdosfunc:
|
||
db coutf
|
||
biosmode:
|
||
db 0 ;0FFh = no bios restore, 07fh = restore
|
||
;only bios jmp, 0 = restore bios jump and
|
||
;resbdos jmp when removed.
|
||
endif
|
||
|
||
functbl: ;preset for console output
|
||
db skipf, skipf, coutf, cstatf, crawf, pbuff
|
||
db cinf, creadf, resetf, resdvf, resalvf, pblkf, eot
|
||
|
||
funcend:
|
||
;
|
||
input: db 0 ;non-zero if putting input to a file
|
||
list: db 0 ;TRUE if list output redirection
|
||
echo: db 1 ;echo output to device
|
||
cooked: ;must be next after echo
|
||
db 0 ;TRUE if ctrl chars displayed with ^
|
||
rsxfun:
|
||
pkillf: db 255 ;put abort routine code
|
||
pfcbf: db 255 ;put FCB display function no.
|
||
; ********** remaining variables must be in this order
|
||
record: db 0 ;counts down records to block boundary
|
||
blm: db 0 ;block mask = records per block (rel 0)
|
||
program: ;This must be @ .putfcb-2
|
||
db 0
|
||
putusr: db 0 ;user number for redirection file
|
||
putfcb: db 1 ;a
|
||
db 'SYSOUT '
|
||
db '$$$'
|
||
db 0,0
|
||
putmod: db 0
|
||
putrc: db 0
|
||
ds 16 ;map
|
||
putcr: db 0
|
||
;
|
||
cbufp: db 0
|
||
movend:
|
||
;*******************************************************************
|
||
end
|
||
|
||
|