mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 09:24:19 +00:00
1053 lines
25 KiB
NASM
1053 lines
25 KiB
NASM
title 'Resident Portion of Banked BDOS'
|
||
;***************************************************************
|
||
;***************************************************************
|
||
;** **
|
||
;** B a s i c D i s k O p e r a t i n g S y s t e m **
|
||
;** **
|
||
;** R e s i d e n t P o r t i o n - B a n k e d B D O S **
|
||
;** **
|
||
;***************************************************************
|
||
;***************************************************************
|
||
|
||
;/*
|
||
; Copyright (C) 1978,1979,1980
|
||
; Digital Research
|
||
; P.O. Box 579
|
||
; Pacific Grove, CA 93950
|
||
;
|
||
; Revised:
|
||
; 11 Jan 80 by Thomas Rolander
|
||
;*/
|
||
|
||
on equ 0ffffh
|
||
off equ 00000h
|
||
;
|
||
org 0000h
|
||
base equ $
|
||
;
|
||
; XDOS jump table below BDOS origin
|
||
pdisp equ $-3
|
||
xdos equ pdisp-3
|
||
|
||
; equates for non graphic characters
|
||
ctlc equ 03h ;control c, abort
|
||
ctld equ 04h ;control d, detach
|
||
ctle equ 05h ;physical eol
|
||
ctlh equ 08h ;backspace
|
||
ctlp equ 10h ;prnt toggle
|
||
ctlq equ 11h ;prnt owner toggle
|
||
ctlr equ 12h ;repeat line
|
||
ctls equ 13h ;stop/start screen
|
||
ctlu equ 15h ;line delete
|
||
ctlx equ 18h ;=ctl-u
|
||
ctlz equ 1ah ;end of file
|
||
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 call equates
|
||
dskinit equ 13
|
||
dskslct equ 14
|
||
dsksetDMA equ 26
|
||
setusercode equ 32
|
||
;
|
||
; XDOS call equates
|
||
poll equ 131
|
||
makeque equ 134
|
||
readque equ 137
|
||
condreadque equ 138
|
||
writeque equ 139
|
||
condwriteque equ 140
|
||
dispatch equ 142
|
||
terminate equ 143
|
||
attach equ 146
|
||
detach equ 147
|
||
sysdtadr equ 154
|
||
;
|
||
; Process Descriptor Offsets
|
||
pname equ 6
|
||
console equ 14
|
||
memseg equ 15
|
||
thread equ 18
|
||
disksetDMA equ 20
|
||
diskselect equ 22
|
||
diskparams equ 23
|
||
searcha equ 26
|
||
drvact equ 28
|
||
;
|
||
; System Data Page Offsets
|
||
userstackflag equ 3
|
||
brkvctr equ 48
|
||
usrstkregion equ 80
|
||
;
|
||
; MP/M Data Page Offsets
|
||
rlros equ 5
|
||
thrdrt equ 17
|
||
cnsatt equ 20
|
||
msegtbl equ 150
|
||
;
|
||
;*****
|
||
;
|
||
; enter here from the user's program with function number
|
||
; in c, and information address in d,e
|
||
jmp xbdos ;to xbdos handler
|
||
jmp bios ;to bios jump table base address
|
||
;
|
||
; bdos/xdos initialization code
|
||
syinit:
|
||
;HL = sysdat page address
|
||
shld sysdat
|
||
mvi l,7! lxi b,bnkbdos
|
||
mov a,m! mov e,a! stax b! inx b! inx h
|
||
mov a,m! mov d,a! stax b
|
||
xchg! inx h! inx h! inx h
|
||
shld bnkbdosinit
|
||
bnkbdosinit equ $+1
|
||
call $-$ ;initialize the banked bdos
|
||
jmp syinitcontd
|
||
|
||
extjmptbl:
|
||
jmp extreboot
|
||
jmp rlr
|
||
jmp getrlradr
|
||
jmp dsplynm
|
||
jmp xprint
|
||
jmp xcrlf
|
||
jmp conoutx
|
||
jmp getmemseg
|
||
jmp coninf
|
||
jmp homef
|
||
jmp seldskf
|
||
jmp settrkf
|
||
jmp setsecf
|
||
jmp setdmaf
|
||
jmp extreadf
|
||
jmp extwritef
|
||
jmp sectran
|
||
|
||
syinitcontd:
|
||
lhld sysdat! mov c,h
|
||
mvi l,252! mov a,m! inx h! mov h,m
|
||
mov l,a! lxi d,0005! dad d
|
||
shld rlradr! mov h,c
|
||
mvi l,userstackflag! mov a,m! sta usrstkflg
|
||
dcr l! mov l,m! mvi h,0 ;HL = RST #
|
||
mov c,l ;put RST # into C for use by SYSINITF
|
||
dad h! dad h! dad h ;HL = breakpoint address
|
||
mvi m,0C3h! inx h ;store jump to brkpt hndlr
|
||
lxi d,brkpt ;DE = brkpt entry address
|
||
mov m,e! inx h! mov m,d
|
||
;initialize jmp at 0000H to fake BIOS jump table
|
||
mvi a,0C3H! sta 0000H
|
||
lxi h,drctjmptbl! shld 0001H
|
||
;execute the XIOS SYSINIT function
|
||
call syinitf
|
||
ei ;in case it was not done in sysinit
|
||
;create disk mutual exclusion queue
|
||
mvi c,makeque! lxi d,diskcqcb! call xdos
|
||
mvi c,writeque! lxi d,MXDisk! call xdos
|
||
;create printer mutual exclusion queue
|
||
mvi c,makeque! lxi d,listcqcb! call xdos
|
||
mvi c,writeque! lxi d,MXList! call xdos
|
||
;get the directory buffer address
|
||
mvi c,0! call seldskf
|
||
lxi d,8! dad d! mov e,m! inx h! mov d,m
|
||
xchg! shld dirbufa
|
||
;initialize disk system
|
||
mvi c,dskinit! jmp bdos
|
||
;ret ;initialization is complete
|
||
;
|
||
CoNm:
|
||
db 'COPYRIGHT (C) 1980, '
|
||
db ' DIGITAL RESEARCH '
|
||
Serial:
|
||
db '654321'
|
||
|
||
lstack equ Serial+4
|
||
|
||
entsp equ lstack ;BDOS entry stack pointer
|
||
|
||
dtbl equ $
|
||
org ((dtbl-base)+0ffh) and 0ff00h
|
||
; *** this table is page aligned
|
||
; BIOS jump table for *.COM file support
|
||
jmp bootf
|
||
drctjmptbl:
|
||
jmp wbootf
|
||
jmp bconst
|
||
jmp bconin
|
||
jmp bconout
|
||
jmp blist
|
||
;
|
||
; Support for direct BIOS console & list device I/O
|
||
;
|
||
bconst: call setflg0
|
||
lxi h,console! dad d! mov d,m
|
||
jmp constf
|
||
|
||
bconin: call setflg0! mvi c,3! jmp xbdos
|
||
|
||
bconout:call setflg0! mov e,c! mvi c,4! jmp xbdos
|
||
|
||
blist: call setflg0! mov e,c! mvi c,5! jmp xbdos
|
||
|
||
setflg0:
|
||
lhld rlradr! mov e,m! inx h! mov d,m
|
||
lxi h,pname! dad d
|
||
mov a,m! ori 80h! mov m,a
|
||
ret
|
||
|
||
; Disk and List data structures
|
||
diskcqcb:
|
||
;disk mutual exclusion circular queue control block
|
||
dw $-$ ;link
|
||
db 'MXDisk ' ;name
|
||
dw 0 ;message length
|
||
dw 1 ;number of messages
|
||
dw $-$ ;dq process head
|
||
dw $-$ ;nq process head
|
||
dw $-$ ;msgin
|
||
dw $-$ ;msgout
|
||
dw $-$ ;msgcnt
|
||
dw $-$ ;owner Process descriptor adr
|
||
MXDisk:
|
||
;disk user queue control block
|
||
dw diskcqcb
|
||
|
||
listcqcb:
|
||
;list mutual exclusion circular queue control block
|
||
dw $-$ ;link
|
||
db 'MXList ' ;name
|
||
dw 0 ;message length
|
||
dw 1 ;number of messages
|
||
dw $-$ ;dq process head
|
||
dw $-$ ;nq process head
|
||
dw $-$ ;msgin
|
||
dw $-$ ;msgout
|
||
dw $-$ ;msgcnt
|
||
dw $-$ ;owner Process Descriptor adr
|
||
MXList:
|
||
;list user queue control block
|
||
dw listcqcb
|
||
|
||
xbdos: ;arrive here from user programs
|
||
mov a,c! ora c ; test function code
|
||
jz reboot ;zero terminates calling process
|
||
jp notXDOS ;jump if a BDOS call
|
||
|
||
call XDOS ;func >= 128 is a XDOS call
|
||
mov a,l ;XDOS returns address put low byte into A
|
||
ret
|
||
|
||
badfunc:
|
||
;invalid function code
|
||
lxi h,0ffffh! mov a,l! ret
|
||
|
||
brkpt: ;debugger breakpoint entry
|
||
di! shld svdhl! pop h! shld svdrt! push psw
|
||
;set HL = RLR
|
||
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
|
||
mvi a,memseg! add l! mov l,a
|
||
mvi a,0! adc h! mov h,a ;HL = .pd.memseg
|
||
mov a,m! add a! adi brkvctr
|
||
lhld sysdat! mov l,a ;HL = brkpt hndlr address
|
||
mov a,m! inx h! mov h,m! mov l,a
|
||
shld jmptobrk+1
|
||
pop psw! lhld svdrt! push h! lhld svdhl
|
||
jmptobrk:
|
||
jmp $-$
|
||
|
||
restore:
|
||
;restore user stack
|
||
xchg! pop h! sphl! xchg ;get user stack pointer
|
||
ret
|
||
|
||
notXDOS:
|
||
lda usrstkflg! ora a
|
||
jz BDOS ; if flag set then change stack
|
||
; get memory segment index
|
||
lhld rlradr! mov a,m! inx h
|
||
mov h,m! mov l,a
|
||
mvi a,memseg! add l! mov l,a
|
||
mvi a,0! adc h! mov h,a
|
||
mov a,m ; A = memory segment index
|
||
inr a! jz BDOS ;no stack change if system process call
|
||
dcr a! add a! adi usrstkregion
|
||
lhld sysdat! mov l,a
|
||
mov a,d! mov b,e ;save DE in AB
|
||
mov e,m! inx h! mov d,m
|
||
lxi h,0! dad sp
|
||
xchg! sphl! push d ;set & save user SP
|
||
lxi h,restore! push h ; setup return address to restore stack
|
||
mov d,a! mov e,b ;restore DE
|
||
|
||
BDOS:
|
||
mov a,c! cpi diskf! jc cnsfunc ;jump if not disk i/o
|
||
cpi nfuncs! jnc badfunc ;skip if invalid #
|
||
push d! push b ;save info & func
|
||
|
||
;test for 'live console' suppression, indicated by
|
||
; process name with high order bit of first char "on"
|
||
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
|
||
lxi b,pname! dad b! mov a,m! ani 80h
|
||
cz func11 ;simulate 'live console' with kbd status chk
|
||
|
||
;obtain entry by getting disk mutual exclusion message
|
||
mvi c,readque! lxi d,MXDisk! call XDOS
|
||
|
||
;setup & jump to banked bdos
|
||
pop b! pop d ;restore info & func
|
||
lxi h,0! dad sp! shld entsp
|
||
lxi sp,lstack
|
||
|
||
;perform the required buffer transfers from
|
||
; the user in common memory
|
||
mov a,c! cpi 17 ;search ?
|
||
jnz skipsrch
|
||
call rlr! push d! lxi d,searcha! dad d! pop d
|
||
mov m,e! inx h! mov m,d
|
||
jmp skipsrchnxt
|
||
skipsrch:
|
||
cpi 18 ;search next ?
|
||
jnz skipsrchnxt
|
||
call rlr! lxi d,searcha! dad d
|
||
mov e,m! inx h! mov d,m
|
||
skipsrchnxt:
|
||
mvi b,0! lxi h,dfctbl-12! dad b
|
||
mov a,m! push psw! push d
|
||
rar! jc cpydmain
|
||
rar! jc cpyfcbin
|
||
jmp nocpyin
|
||
cpydmain:
|
||
call rlr! lxi d,disksetdma! dad d
|
||
mov e,m! inx h! mov d,m
|
||
xchg! shld dmabufa! xchg
|
||
lhld dirbufa! mvi b,128
|
||
call move
|
||
pop d! push d
|
||
cpyfcbin:
|
||
lxi h,commonfcb! mvi b,36
|
||
call move
|
||
lxi d,commonfcb
|
||
|
||
nocpyin:
|
||
call getmemseg! sta usermemseg
|
||
mvi m,0 ;set memseg to 0 (memseg #0 must be bank zero)
|
||
push d! push b ;save info & func
|
||
mvi c,dispatch! call xdos
|
||
pop b! pop d
|
||
|
||
bnkbdos equ $+1
|
||
call $-$
|
||
|
||
shld aret
|
||
call getmemseg! lda usermemseg! mov m,a
|
||
mvi c,dispatch! call xdos
|
||
|
||
pop d! pop psw ;resore dfctbl byte & fcb address
|
||
ral! jc dmacpyout
|
||
ral! jnc nocpyout
|
||
fcbcpyout:
|
||
lxi h,commonfcb! xchg! mvi b,36
|
||
jmp cpyoutcmn
|
||
dmacpyout:
|
||
lhld dirbufa! xchg! lhld dmabufa! mvi b,128
|
||
cpyoutcmn:
|
||
call move
|
||
|
||
nocpyout:
|
||
lhld entsp! sphl ;user stack restored
|
||
lhld aret! push h
|
||
;release disk mutual exclusion message
|
||
mvi c,writeque! lxi d,MXDisk! call XDOS
|
||
;function done
|
||
pop h! mov a,l! mov b,h ;BA = HL = aret
|
||
ret
|
||
|
||
move:
|
||
;move data length of B from source DE to
|
||
;destination HL
|
||
inr b ;in case of length=0
|
||
move0:
|
||
dcr b! rz
|
||
ldax d! mov m,a
|
||
inx d! inx h
|
||
jmp move0
|
||
|
||
cnsfunc:
|
||
mov a,c! mov c,e! mov b,d
|
||
lxi h,functab! mov e,a! mvi d,0 ;DE=func, HL=.functab
|
||
dad d! dad d! mov e,m! inx h! mov d,m ;DE=functab(func)
|
||
xchg! pchl ;dispatched
|
||
;
|
||
; dispatch table for functions
|
||
functab:
|
||
dw bootf,func1,func2,func3
|
||
dw func4,listf,func6,func7
|
||
dw cmnret,func9,func10,func11
|
||
diskf equ ($-functab)/2
|
||
|
||
nfuncs equ 40 ;must match with banked bdos # fns
|
||
|
||
;
|
||
func1:
|
||
;return console character with echo
|
||
call attcns! call conech
|
||
mov l,a! ret
|
||
;
|
||
func2:
|
||
;write console character with tab expansion
|
||
call attcns! jmp tabout
|
||
;
|
||
func3:
|
||
;return raw unattached console character
|
||
call testcnsatt
|
||
jmp dirinp
|
||
;
|
||
func4:
|
||
;write raw unattached console character
|
||
call testcnsatt
|
||
jmp conoutf
|
||
;
|
||
;func5:
|
||
;write list character
|
||
;write to list device
|
||
;jmp listf
|
||
;
|
||
func6:
|
||
;direct console i/o - read if 0ffh
|
||
call attcns
|
||
mov a,c! inr a! jz dirinp ;0ffh => 00h, means input mode
|
||
inr a! jz stsinp ;0feh => 00h, means status chk
|
||
;direct output function
|
||
jmp conoutf
|
||
dirinp:
|
||
;this differs from CP/M 2.0 which does const
|
||
;and returns zero if not ready
|
||
;character is ready, get it
|
||
lxi h,kbchar! call ofsthl
|
||
mov a,m! mvi m,0! ora a
|
||
cz coninf ;to A
|
||
mov l,a! ret
|
||
stsinp:
|
||
;direct console status input
|
||
call constf ;to A
|
||
mov l,a! ret
|
||
;
|
||
func7:
|
||
;return io byte
|
||
;*** Not implemented in MP/M 1.0 ***
|
||
xra a
|
||
mov l,a! ret
|
||
;
|
||
;func8:
|
||
;set i/o byte
|
||
;*** Not implemented in MP/M 1.0 ***
|
||
;ret
|
||
;
|
||
func9:
|
||
;write line until $ encountered
|
||
;BC = string address
|
||
call attcns! jmp print ;out to console
|
||
;
|
||
func10:
|
||
;read a buffered console line
|
||
call attcns! jmp read
|
||
;
|
||
func11:
|
||
;check console status
|
||
call testcnsatt
|
||
jz doconbrk
|
||
mvi c,dispatch! call xdos
|
||
xra a! mov l,a! ret
|
||
doconbrk:
|
||
call conbrk
|
||
mov l,a
|
||
;
|
||
cmnret:
|
||
ret
|
||
;
|
||
getrlradr:
|
||
lhld rlradr! ret
|
||
|
||
rlr:
|
||
;set HL = contents of Ready List Root
|
||
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
|
||
ret
|
||
;
|
||
getmemseg:
|
||
;set A = memory segment #
|
||
call rlr ;HL = Ready List Root
|
||
mvi a,memseg! add l! mov l,a
|
||
mvi a,0! adc h! mov h,a ;HL = .pd.memseg
|
||
mov a,m! ret
|
||
;
|
||
testcnsatt:
|
||
;test to determine if console is attached
|
||
;Zero = attached, D = Console #
|
||
call rlr! xchg ;DE = Ready List Root
|
||
lxi h,console! dad d! mov a,m! push psw! push b
|
||
lhld rlradr! lxi b,cnsatt-rlros! dad b
|
||
add a! mov c,a! mvi b,0! dad b
|
||
mov a,m! cmp e! jnz testext
|
||
inx h! mov a,m! cmp d
|
||
testext:
|
||
pop b! pop d
|
||
mvi e,0 ;cns req'd flag false
|
||
ret
|
||
;
|
||
attcns:
|
||
;attach console if req'd
|
||
call testcnsatt
|
||
mvi e,0ffh! rz ;cns req'd flag true
|
||
push b! push d!
|
||
mvi c,attach! call xdos
|
||
pop d! pop b!
|
||
ret
|
||
;
|
||
ofsthl:
|
||
;offset HL by console # (in D)
|
||
push psw
|
||
mov a,d! add l! mov l,a
|
||
mvi a,0! adc h! mov h,a
|
||
pop psw
|
||
ret
|
||
|
||
;
|
||
; console handlers
|
||
|
||
constx:
|
||
push d! call constf! pop d! ret
|
||
|
||
coninx:
|
||
;returns char & cond code = NZ if raw input
|
||
push d! call rlr! lxi d,pname! dad d
|
||
pop d! push d! ;restore console #
|
||
mov a,m! ani 80h! push psw
|
||
call coninf
|
||
mov b,a! pop psw! mov a,b
|
||
pop d! ret
|
||
|
||
conoutx:
|
||
push d! call conoutf! pop d! ret
|
||
|
||
conin:
|
||
;read console character to A
|
||
lxi h,kbchar! call ofsthl
|
||
mov a,m! mvi m,0! ora a! rnz
|
||
;no previous keyboard character ready
|
||
call getchr ;get character externally and test it
|
||
jmp conin ;only exit is with kbchar <> 0
|
||
;ret
|
||
;
|
||
conech:
|
||
;read character with echo
|
||
call conin! call echoc! rc ;echo character?
|
||
;character must be echoed before return
|
||
push psw! mov c,a! call tabout! pop psw
|
||
ret ;with character in A
|
||
;
|
||
echoc:
|
||
;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: ;check for character ready
|
||
call constx! ani 1
|
||
lxi h,kbchar! call ofsthl
|
||
jnz pgetchr ;jump if char to be read in
|
||
mov a,m! ora a! rz ;return if no char in kbchar either
|
||
jmp conb1 ;active kbchar
|
||
pgetchr:
|
||
mvi m,0 ;clear kbchar to prepare for new char
|
||
;character ready, read it
|
||
getchr: ;entry point used by conin
|
||
call coninx ;to A
|
||
jnz conb0; skip char testing if pd.pname.f0 is "on"
|
||
cpi ctls! jnz notcts ;check stop screen function
|
||
;found ctls, read next character
|
||
call coninx ;to A
|
||
cpi ctlc! jz controlc ;ctlc implies re-boot
|
||
;not a reboot, act as if nothing has happened
|
||
xra a! ret ;with zero in accumulator
|
||
notcts:
|
||
;not a control s, control d?
|
||
cpi ctld! jnz notctd
|
||
;found ctld, detach console
|
||
push d! mvi c,detach! call XDOS
|
||
;then attach console back
|
||
; unless cns not req'd
|
||
pop d! mov a,e! ora a
|
||
rz! push d ;return if cns not req'd
|
||
mvi c,attach! call XDOS! pop d
|
||
;print console attach message
|
||
lxi b,atchmsg! call xprint
|
||
call rlr
|
||
dsplynm:
|
||
lxi b,pname! dad b! mvi e,8
|
||
dsploop:
|
||
mov c,m! push h! push d! call conoutx
|
||
pop d! pop h! inx h! dcr e
|
||
jnz dsploop
|
||
inr e ;cns req'd set true
|
||
xcrlf:
|
||
;output crlf without CONBRK calls
|
||
mvi c,cr! call conoutx
|
||
mvi c,lf! call conoutx
|
||
xra a! ret ;with zero in A
|
||
|
||
notctd:
|
||
;not a control d, control c?
|
||
cpi ctlc! jnz conb0
|
||
controlc: ;entry point
|
||
;test to see if this is a user process
|
||
call getmemseg! inr a
|
||
rz ;ignore ^C if system process running
|
||
;print Abort (Y/N) ?
|
||
lxi b,abtmsg! call query
|
||
jz reboot
|
||
xra a! ret ;with zero in A
|
||
conb0:
|
||
;character in accum, save it
|
||
lxi h,kbchar! call ofsthl! mov m,a
|
||
conb1:
|
||
;return with true set in accumulator
|
||
mvi a,1! ret
|
||
;
|
||
query:
|
||
call xprint! call coninx! push psw
|
||
mov c,a! call conoutx
|
||
mvi c,cr! call conoutx
|
||
mvi c,lf! call conoutx
|
||
pop psw
|
||
ani 5fh! cpi 'Y'
|
||
ret
|
||
;
|
||
conout:
|
||
;compute character position/write console char from C
|
||
;compcol = true if computing column position
|
||
lxi h,compcol! call ofsthl
|
||
mov a,m! ora a! jnz compout
|
||
;write the character, then compute the column
|
||
;write console character from C
|
||
push b! call conoutx ;externally, to console
|
||
call conbrk ;check for screen stop function
|
||
pop b! push b! push d ;recall/save character & con #
|
||
;may be copying to the list device
|
||
lxi h,listcp! call ofsthl
|
||
mov a,m! ani 01h! cnz listf ;to printer, if so
|
||
pop d! pop b ;recall the character & con #
|
||
compout:
|
||
mov a,c ;recall the character
|
||
;and compute column position
|
||
lxi h,column! call ofsthl ;A = char, HL = .column
|
||
cpi rubout! rz ;no column change if nulls
|
||
inr m ;column = column + 1
|
||
cpi ' '! rnc ;return if graphic
|
||
;not graphic, reset column position
|
||
dcr m ;column = column - 1
|
||
mov a,m! ora a! rz ;return if at zero
|
||
;not at zero, may be backspace or end line
|
||
mov a,c ;character back to A
|
||
cpi ctlh! jnz notbacksp
|
||
;backspace character
|
||
dcr m ;column = column - 1
|
||
ret
|
||
notbacksp:
|
||
;not a backspace character, eol?
|
||
cpi lf! rnz ;return if not
|
||
;end of line, column = 0
|
||
mvi m,0 ;column = 0
|
||
ret
|
||
;
|
||
ctlout:
|
||
;send C character with possible preceding up-arrow
|
||
mov a,c! call echoc ;cy if not graphic (or special case)
|
||
jnc tabout ;skip if graphic, tab, cr, lf, or ctlh
|
||
;send preceding up arrow
|
||
push psw! mvi c,ctl! call conout ;up arrow
|
||
pop psw! ori 40h ;becomes graphic letter
|
||
mov c,a ;ready to print
|
||
;(drop through to tabout)
|
||
;
|
||
tabout:
|
||
;expand tabs to console
|
||
mov a,c! cpi tab! jnz conout ;direct to conout if not
|
||
;tab encountered, move to next tab position
|
||
tab0:
|
||
mvi c,' '! call conout ;another blank
|
||
call ldacolumn! ani 111b ;column mod 8 = 0 ?
|
||
jnz tab0 ;back for another if not
|
||
ret
|
||
;
|
||
backup:
|
||
;back-up one screen position
|
||
call pctlh! mvi c,' '! call conoutx ;jmp pctlh
|
||
;
|
||
pctlh:
|
||
;send ctlh to console without affecting column count
|
||
mvi c,ctlh! jmp conoutx
|
||
;ret
|
||
;
|
||
crlfp:
|
||
;print #, cr, lf for ctlx, ctlu, ctlr functions
|
||
;then move to strtcol (starting column)
|
||
mvi c,'#'! call conout
|
||
call crlf
|
||
;column = 0, move to position strtcol
|
||
crlfp0:
|
||
call ldacolumn! lxi h,strtcol! call ofsthl
|
||
cmp m! rnc ;stop when column reaches strtcol
|
||
mvi c,' '! call conout ;print blank
|
||
jmp crlfp0
|
||
;;
|
||
;
|
||
crlf:
|
||
;carriage return line feed sequence
|
||
mvi c,cr! call conout! mvi c,lf! jmp conout
|
||
;ret
|
||
;
|
||
xprint:
|
||
;print routine which does not CONBRK
|
||
;BC = string address, string terminated with a '$'
|
||
ldax b! cpi '$'! rz
|
||
push b! mov c,a! call conoutx! pop b
|
||
inx b! jmp xprint
|
||
;
|
||
print:
|
||
;print message until M(BC) = '$'
|
||
ldax b! cpi '$'! rz ;stop on $
|
||
;more to print
|
||
inx b! push b! mov c,a ;char to C
|
||
call tabout ;another character printed
|
||
pop b! jmp print
|
||
;
|
||
pread: ;entry to read, restores buffer address
|
||
pop b
|
||
read: ;BC = address (max length, current length, buffer)
|
||
push b ;save buffer address for possible ^X or ^U
|
||
call ldacolumn
|
||
lxi h,strtcol! call ofsthl
|
||
mov m,a ;save start for ctl-x, ctl-h
|
||
mov h,b! mov l,c! mov c,m! inx h! push h! mvi b,0
|
||
;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
|
||
ani 7fh ;mask parity bit
|
||
pop h! pop b ;reactivate counters
|
||
cpi cr! jz readen ;end of line?
|
||
cpi lf! jz readen ;also end of line
|
||
cpi ctlh! jnz noth ;backspace?
|
||
;do we have any characters to back over?
|
||
mov a,b! ora a! jz readnx
|
||
;characters remain in buffer, backup one
|
||
dcr b ;remove one character
|
||
call ldacolumn
|
||
lxi h,compcol! call ofsthl
|
||
mov m,a ;col > 0
|
||
;compcol > 0 marks repeat as length compute
|
||
jmp linelen ;uses same code as repeat
|
||
noth:
|
||
;not a backspace
|
||
cpi rubout! jnz notrub ;rubout char?
|
||
;rubout encountered, rubout if possible
|
||
mov a,b! ora a! jz readnx ;skip if len=0
|
||
;buffer has characters, resend last char
|
||
mov a,m! dcr b! dcx h ;A = last char
|
||
;blen=blen-1, next to fill - 1 decremented
|
||
jmp rdech1 ;act like this is an echo
|
||
;
|
||
notrub:
|
||
;not a rubout character, check end line
|
||
cpi ctle! jnz note ;physical end line?
|
||
;yes, save active counters and force eol
|
||
push b! push h! call crlf
|
||
lxi h,strtcol! call ofsthl
|
||
xra a! mov m,a ;start position = 00
|
||
jmp readn0 ;for another character
|
||
note:
|
||
;not end of line, list toggle?
|
||
cpi ctlp! jnz notp ;skip if not ctlp
|
||
mvi a,01h! jmp ctlpqcmn
|
||
notp:
|
||
cpi ctlq! jnz notq ;skip if not ctlq
|
||
mvi a,80h
|
||
ctlpqcmn:
|
||
;list toggle - change parity
|
||
push h ;save next to fill - 1
|
||
push b! push d
|
||
lxi h,listcp! call ofsthl ;HL=.listcp flag
|
||
xra m! mov m,a ;listcp=-listcp
|
||
push h ;save address of listcp
|
||
jnz prntron ; jump if printer to be turned on
|
||
prntroff:
|
||
;return list mutex queue message
|
||
mvi m,0! ;zero listcp(console)
|
||
mvi c,condwriteque! lxi d,MXList
|
||
call XDOS
|
||
pop h! jmp ctlpxit
|
||
prntron:
|
||
;test for ^p or ^q already "on"
|
||
cpi 81h! jz prntroff
|
||
;cond. read list mutex message
|
||
mvi c,condreadque
|
||
lxi d,MXList! call XDOS
|
||
mov a,l! ora a
|
||
pop h! jz ctlpxit
|
||
;printer busy, could not ^p
|
||
mvi m,0! lxi b,pbsymsg
|
||
;D = console #
|
||
pop d! push d
|
||
call xprint
|
||
ctlpxit:
|
||
pop d! pop b
|
||
pop h! jmp readnx ;for another char
|
||
notq:
|
||
;not a ctlp, line delete?
|
||
cpi ctlx! jnz notx
|
||
pop h ;discard start position
|
||
;loop while column > strtcol
|
||
backx:
|
||
lxi h,strtcol! call ofsthl
|
||
mov a,m! lxi h,column! call ofsthl
|
||
cmp m! jnc pread ;start again
|
||
dcr m ;column = column - 1
|
||
call backup ;one position
|
||
jmp backx
|
||
notx:
|
||
;not a control x, control u?
|
||
cpi ctlu! jnz notu ;skip if not
|
||
;delete line (ctlu)
|
||
call crlfp ;physical eol
|
||
pop h ;discard starting position
|
||
jmp pread ;to start all over
|
||
notu:
|
||
;not line delete, repeat line?
|
||
cpi ctlr! jnz notr
|
||
linelen:
|
||
;repeat line, or compute line len (ctlh)
|
||
;if compcol > 0
|
||
push b! call crlfp ;save line length
|
||
pop b! pop h! push h! push b
|
||
;bcur, cmax active, beginning buff at HL
|
||
rep0:
|
||
mov a,b! ora a! jz rep1 ;count len to 00
|
||
inx h! mov c,m ;next to print
|
||
dcr b! push b! push h ;count length down
|
||
call ctlout ;character echoed
|
||
pop h! pop b ;recall remaining count
|
||
jmp rep0 ;for the next character
|
||
rep1:
|
||
;end of repeat, recall lengths
|
||
;original BC still remains pushed
|
||
push h ;save next to fill
|
||
lxi h,compcol! call ofsthl
|
||
mov a,m! ora a ;>0 if computing length
|
||
jz readn0 ;for another char if so
|
||
;column position computed for ctlh
|
||
lxi h,column! call ofsthl! sub m ;diff > 0
|
||
lxi h,compcol! call ofsthl
|
||
mov m,a ;count down below
|
||
;move back compcol-column spaces
|
||
backsp:
|
||
;move back one more space
|
||
call backup ;one space
|
||
lxi h,compcol! call ofsthl! dcr m
|
||
jnz backsp
|
||
jmp readn0 ;for next character
|
||
notr:
|
||
;not a ctlr, 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
|
||
mov c,a ;ready to print
|
||
call ctlout ;may be up-arrow C
|
||
pop h! pop b! mov a,b ;len to A
|
||
;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
|
||
pop h ;discard buffer address
|
||
mvi c,cr! jmp conout ;return carriage
|
||
;ret
|
||
;
|
||
ldacolumn:
|
||
lxi h,column! call ofsthl! mov a,m! ret
|
||
|
||
pbsymsg:
|
||
db cr,lf,'Printer Busy.',cr,lf,'$'
|
||
|
||
abtmsg:
|
||
db cr,lf,'Abort (Y/N) ?','$'
|
||
|
||
atchmsg:
|
||
db cr,lf,'Attach:$'
|
||
|
||
;
|
||
; data areas
|
||
;
|
||
nmbcns equ 16
|
||
|
||
compcol:db 0 ;true if computing column position
|
||
rept nmbcns-1
|
||
db 0
|
||
endm
|
||
strtcol:db 0 ;starting column position after read
|
||
rept nmbcns-1
|
||
db 0
|
||
endm
|
||
column: db 0 ;column position
|
||
rept nmbcns-1
|
||
db 0
|
||
endm
|
||
listcp: db 0 ;listing toggle
|
||
rept nmbcns-1
|
||
db 0
|
||
endm
|
||
kbchar: db 0 ;initial key char = 00
|
||
rept nmbcns-1
|
||
db 0
|
||
endm
|
||
|
||
;*********
|
||
;
|
||
; intercept bios boot, readf & writef to switch banks
|
||
|
||
extreboot:
|
||
call getmemseg! lda usermemseg! mov m,a
|
||
mvi c,dispatch! call xdos
|
||
lxi h,0ffffh! shld aret
|
||
lda usermemseg! inr a
|
||
jz nocpyout ;system process - release MXDisk & return
|
||
;
|
||
reboot:
|
||
;terminate the calling process
|
||
mvi c,terminate! lxi d,0
|
||
jmp xdos
|
||
|
||
|
||
extreadf:
|
||
call getmemseg! lda usermemseg! mov m,a
|
||
mvi c,dispatch! call xdos
|
||
call readf
|
||
jmp extcommon
|
||
|
||
extwritef:
|
||
call getmemseg! lda usermemseg! mov m,a
|
||
mvi c,dispatch! call xdos
|
||
call writef
|
||
extcommon:
|
||
push psw
|
||
call getmemseg! mvi m,0
|
||
mvi c,dispatch! call xdos
|
||
pop psw! ret
|
||
|
||
;
|
||
; Local Data Segment
|
||
rlradr: ds 2 ;address of Ready List Root
|
||
sysdat: ds 2 ;address of system data page
|
||
usrstkflg: ds 1 ;user stack flag, 0ffh=users stack
|
||
svdhl: ds 2 ;saved HL at breakpoint entry
|
||
svdrt: ds 2 ;saved return address at breakpoint entry
|
||
;
|
||
dirbufa: ds 2 ;directory buffer address
|
||
dmabufa: ds 2 ;dma buffer address
|
||
usermemseg: ds 1 ;saved user mem seg index
|
||
aret: ds 2 ;address value to return
|
||
|
||
commonfcb:
|
||
ds 36 ;fcb copy in common memory
|
||
|
||
;
|
||
; Disk Function Copy Table
|
||
;
|
||
dmain equ 00000001b ;dma copy on entry
|
||
fcbin equ 00000010b ;fcb copy on entry
|
||
dmaout equ 10000000b ;dma copy on exit
|
||
fcbout equ 01000000b ;fcb copy on exit
|
||
|
||
dfctbl:
|
||
db 0 ; 12=return version #
|
||
db 0 ; 13=reset disk system
|
||
db 0 ; 14=select disk
|
||
db fcbin+fcbout ; 15=open file
|
||
db fcbin ; 16=close file
|
||
db fcbin+dmain+dmaout ; 17=search first
|
||
db fcbin+dmain+dmaout ; 18=search next
|
||
db fcbin ; 19=delete file
|
||
db fcbin+fcbout ; 20=read sequential
|
||
db fcbin+fcbout ; 21=write sequential
|
||
db fcbin+fcbout ; 22=make file
|
||
db fcbin ; 23=rename file
|
||
db 0 ; 24=return login vector
|
||
db 0 ; 25=return current disk
|
||
db 0 ; 26=set DMA address
|
||
db 0 ; 27=get alloc address
|
||
db 0 ; 28=write protect disk
|
||
db 0 ; 29=get R/O vector
|
||
db fcbin ; 30=set file attributes
|
||
db 0 ; 31=get disk param addr
|
||
db 0 ; 32=get/set user code
|
||
db fcbin+fcbout ; 33=read random
|
||
db fcbin+fcbout ; 34=write random
|
||
db fcbin+fcbout ; 35=compute file size
|
||
db fcbin+fcbout ; 36=set random record
|
||
db 0 ; 37=drive reset
|
||
db 0 ; 38=access drive
|
||
db 0 ; 39=free drive
|
||
|
||
|
||
ds 6 ;reserve space for two jump instructions
|
||
;
|
||
; bios external jump table
|
||
last:
|
||
org (((last-base)+255) AND 0ff00h) - 6
|
||
jmp xbdos
|
||
jmp pdisp
|
||
;
|
||
; bios access table
|
||
bios equ $ ;base of the bios jump table
|
||
bootf equ bios ;cold boot function
|
||
wbootf equ bootf+3 ;warm boot function
|
||
constf equ wbootf+3 ;console status function
|
||
coninf equ constf+3 ;console input function
|
||
conoutf equ coninf+3 ;console output function
|
||
listf equ conoutf+3 ;list output function
|
||
punchf equ listf+3 ;punch output function
|
||
readerf equ punchf+3 ;reader input function
|
||
homef equ readerf+3 ;disk home function
|
||
seldskf equ homef+3 ;select disk function
|
||
settrkf equ seldskf+3 ;set track function
|
||
setsecf equ settrkf+3 ;set sector function
|
||
setdmaf equ setsecf+3 ;set dma function
|
||
readf equ setdmaf+3 ;read disk function
|
||
writef equ readf+3 ;write disk function
|
||
liststf equ writef+3 ;list status function
|
||
sectran equ liststf+3 ;sector translate
|
||
;
|
||
; xios access table
|
||
xiosms equ sectran+3 ;memory select / protect
|
||
xiospl equ xiosms+3 ;device poll
|
||
strclk equ xiospl+3 ;start clock
|
||
stpclk equ strclk+3 ;stop clock
|
||
exitr equ stpclk+3 ;exit critical region
|
||
maxcns equ exitr+3 ;max console #
|
||
syinitf equ maxcns+3 ;MP/M system initialization
|
||
;
|
||
end
|
||
|