Files
Pegasys-RomWBW/Source/CPM22/CCP.ASM
2014-09-08 04:11:55 +00:00

1287 lines
26 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
title 'console command processor (CCP), ver 2.2'
;
; assembly language version of the cpm console command processor
;
; version 2.2 February, 1980
;
; copyright (c) 1976, 1977, 1978, 1979, 1980
;
; Digital Research
; Box 579, Pacific Grove,
; California, 93950
;
false equ 0000h
true equ not false
testing equ false ;true if testing
;
;
if testing
org 3400h
bdosl equ $+800h ;bdos location
else
org 0d000h
bdosl equ $+800h ;bdos location
endif
tran equ 100h
tranm equ $
ccploc equ $
;
; *************************************************************
; * base of ccp contains the following code/data *
; * ccp: jmp ccpstart (start with command) *
; * jmp ccpclear (start, clear command) *
; * ccp+6 127 (max command length) *
; * ccp+7 comlen (command length = 00) *
; * ccp+8 ' ... ' (16 blanks) *
; *************************************************************
; * Normal entry is at ccp, where the command line given *
; * at ccp+8 is executed automatically (normally a null *
; * command with comlen = 00). An initializing program *
; * can be automatically loaded by storing the command at *
; * ccp+8, with the command length at ccp+7. In this *
; * case, the ccp executes the command before prompting *
; * console for input. Note that the command is exe- *
; * cuted on both warm and cold starts. When the command *
; * line is initialized, a jump to "jmp ccpclear" dis- *
; * ables the automatic command execution. *
; *************************************************************
;
jmp ccpstart ;start ccp with possible initial command
jmp ccpclear ;clear the command buffer
maxlen: db 127 ;max buffer length
comlen: db 0 ;command length (filled in by dos)
; ;command executed initially in comlen non zero
combuf:
db ' ' ;8 character fill
db ' ' ;8 character fill
db 'copyright (c) 1979, digital research '; 38
ds 128-($-combuf)
;
; ;total buffer length is 128 characters
comaddr:dw combuf ;address of next character to scan
staddr: ds 2 ;starting address of current fillfcb request
;
diska equ 0004h ;disk address for current disk
bdos equ 0005h ;primary bdos entry point
buff equ 0080h ;default buffer
fcb equ 005ch ;default file control block
;
rcharf equ 1 ;read character function
pcharf equ 2 ;print character function
pbuff equ 9 ;print buffer function
rbuff equ 10 ;read buffer function
breakf equ 11 ;break key function
liftf equ 12 ;lift head function (no operation)
initf equ 13 ;initialize bdos function
self equ 14 ;select disk function
openf equ 15 ;open file function
closef equ 16 ;close file function
searf equ 17 ;search for file function
searnf equ 18 ;search for next file function
delf equ 19 ;delete file function
dreadf equ 20 ;disk read function
dwritf equ 21 ;disk write function
makef equ 22 ;file make function
renf equ 23 ;rename file function
logf equ 24 ;return login vector
cself equ 25 ;return current selected drive number
dmaf equ 26 ;set dma address
userf equ 32 ;set user number
;
;special fcb flags
;
rofile equ 9 ;read only file
sysfile equ 10 ;system file flag
;
;special characters
;
cr equ 13 ;carriage return
lf equ 10 ;line feed
la equ 5fh ;left arrow
eofile equ 1ah ;end of file
;
;utility procedures
;
printchar:
mov e,a
mvi c,pcharf
jmp bdos
;
printbc: ;print character but save bc registers
push b
call printchar
pop b
ret
;
crlf: mvi a,cr
call printbc
mvi a,lf
jmp printbc
;
blank: mvi a,' '
jmp printbc
;
print: ;print string starting at bc until next 00
push b ; entry
call crlf
pop h ;now print the string
prin0: mov a,m
ora a
rz ;stop on 00
inx h
push h ;ready for next
call printchar ;charcter printed
pop h
jmp prin0 ;for another character
;
initialize:
mvi c,initf
jmp bdos
;
select: mov e,a
mvi c,self
jmp bdos
;
bdos$inr:
call bdos
sta dcnt
inr a
ret
;
open: ;open the file given by d,e
mvi c,openf
jmp bdos$inr
;
openc: ;open comfcb
xra a
sta comrec ;clear next record to read
lxi d,comfcb
jmp open
;
close: ;close the file given by d,e
mvi c,closef
jmp bdos$inr
;
search: ;search for the file given by d,e
mvi c,searf
jmp bdos$inr
;
searchn: ;search for the next occurance of the file
mvi c,searnf ; given by d,e
jmp bdos$inr
;
searchcom: ;search for comfcb file
lxi d,comfcb
jmp search
;
delete: ;delete the fle given by d,e
mvi c,delf
jmp bdos
;
bdos$cond:
call bdos
ora a
ret
;
diskread: ;read the next record from the file given
mvi c,dreadf ; by d,e
jmp bdos$cond
;
diskreadc: ;read the comfcb file
lxi d,comfcb
jmp diskread
;
diskwrite: ;write the next record to the file given
mvi c,dwritf ; by d,e
jmp bdos$cond
;
make: ;create the file given by d,e
mvi c,makef
jmp bdos$inr
;
renam: ;rename the file given by d,e
mvi c,renf
jmp bdos
;
getuser: ;return current user code in a
mvi e,0ffh ;drop through to setuser
;
setuser:
mvi c,userf
jmp bdos ;sets user number
;
saveuser: ;save eser#/disk# before possible ^C or
call getuser ; transient; code to a
add a
add a
add a
add a ;rotate left
lxi h,cdisk
ora m ;4b = user, 4b = disk
sta diska ;stored away in memory for later
ret
;
setdiska:
lda cdisk
sta diska ;user/disk
ret
;
translate: ;translate character in register a to upper
cpi 61h ; case; return if below lower case a
rc
cpi 7bh ;return if above lower case z
rnc
ani 5fh ;translated to upper case
ret
;
readcom: ;read the next command into the command buffer
; check for submit file
lda submit
ora a
jz nosub
; ;scanning a submit file
;change drives to open and read the file
lda cdisk
ora a
mvi a,0
cnz select ;have to open again in case xsub present
;
lxi d,subfcb
call open
jz nosub ;skip if nosub
;
lda subrc
dcr a ;read last record(s) first
sta subcr ;current record to read
lxi d,subfcb
call diskread ;end of file if last record
jnz nosub
;
;disk read is ok, transfer to combuf
lxi d,comlen
lxi h,buff
mvi b,128
call move0 ;line is transfered, close the file with
; a deleted record
lxi h,submod
mvi m,0 ;clear fwflag
inx h
dcr m ;one less record
lxi d,subfcb
call close
jz nosub ;close went ok, return to original drive
;
lda cdisk
ora a
cnz select ;print to the 00
lxi h,combuf
call prin0
call break$key
jz noread
call del$sub
jmp ccp ;break key depressed
;
nosub: call delsub ;translate to upper case, store zero at end
call saveuser ;user number save in case ^C
mvi c,rbuff
lxi d,maxlen
call bdos
call setdiska ;no control-C do restore diska
;
noread: ;enter here from submit file
lxi h,comlen ;set the last character to zero for later scans
mov b,m ;length is in b
;
readcom0:
inx h
mov a,b
ora a ;end of scan
jz readcom1
mov a,m ;get character and translate
call translate
mov m,a
dcr b
jmp readcom0
;
readcom1: ;end of scan, h,l address end of command
mov m,a ;store a zero
lxi h,combuf
shld comaddr ;ready to scan to zero
ret
;
break$key: ;check for a character ready at console
mvi c,breakf
call bdos
ora a
rz
mvi c,rcharf
call bdos ;character cleared
ora a
ret
;
cselect: ;get currently selected drive number to reg a
mvi c,cself
jmp bdos
;
setdmabuff: ;set default buffer dma address
lxi d,buff ; (drop through)
;
setdma: ;set dma address to d,e
mvi c,dmaf
jmp bdos
;
del$sub: ;delete the submit file, and set submit flag
lxi h,submit
mov a,m
ora a
rz ;return if no submit file
mvi m,0 ;submit flag is set to false
xra a
call select ;on drive a to erase file
lxi d,subfcb
call delete
lda cdisk
jmp select ;back to original drive
;
serialize: ;check serialization
lxi d,serial
lxi h,bdosl
mvi b,6 ;check 6 bytes
;
ser0: ldax d
cmp m
jnz badserial
inx d
inx h
dcr b
jnz ser0
ret ;serial number is ok
;
comerr: ;error in command string starting at
call crlf ; position 'staddr' and ending with first
lhld staddr ; delimeter, h,l address first to print
;
comerr0: ;print characters until blank or zero
mov a,m
cpi ' '
jz comerr1 ;not blank
ora a
jz comerr1 ;not 0, so print it
push h
call printchar
pop h
inx h
jmp comerr0 ;for another character
;
comerr1: ;print question mark and delete sub file
mvi a,'?'
call printchar
call crlf
call del$sub
jmp ccp ;restart with next command
;
;FCB scan and fill subroutine (entry is at
; fillfcb below)
;fill the comfcb, indexed by a (0 or 16)
;subroutines
;
delim: ;look for a delimeter
ldax d
ora a
rz ;not the last element
cpi ' '
jc comerr ;non graphic
rz ;treat blank as delimeter
cpi '='
rz
cpi la ;left arrow
rz
cpi '.' ;period
rz
cpi ':' ;colon
rz
cpi ';' ;semicolon
rz
cpi '<' ;left angle bracket
rz
cpi '>' ;right angle bracket
rz
ret ;delimeter not found
;
deblank: ;deblank the input line
ldax d
ora a
rz ;treat end of line as blank
cpi ' '
rnz
inx d
jmp deblank
;
addh: ;add a to h,l
add l
mov l,a
rnc
inr h
ret
;
fillfcb0: ;equivalent to fillfcb(0)
mvi a,0
;
fillfcb:
lxi h,comfcb
call addh
push h
push h ;fcb rescanned at [?]-
xra a
sta sdisk ;clear selected disk (in case a:...)
lhld comaddr
xchg ;command address in d,e
call deblank ;to first non blank character
xchg
shld staddr
xchg
pop h ;d,e has command, h,l has fcb address
;look for preceding file name a: b: ...
ldax d
ora a
jz setcur0 ;use current disk of empty command
;
sbi 'A'-1
mov b,a ;disk name held in b if ':' follows
inx d
ldax d
cpi ':'
jz setdsk ;set disk name if :
;
setcur: ;set current disk
dcx d ;back to first character of command
;
setcur0:
lda cdisk
mov m,a
jmp setname
;
setdsk: ;set disk to name in register b
mov a,b
sta sdisk ;mark as disk selected
mov m,b
inx d ;past the :
;
setname: ;set the file name field
mvi b,8 ;file name length, (max)
;
setnam0:
call delim
jz padname ;not a delimeter
inx h
cpi '*'
jnz setnam1 ;must be ?'s
mvi m,'?'
jmp setnam2 ;to dec count
;
setnam1:
mov m,a ;store character in fcb
inx d
;
setnam2:
dcr b ;coutn down length
jnz setnam0
;
;end of name, truncate remainder
tryname:
call delim
jz setty ;set type field if delimeter
inx d
jmp tryname
;
padname:
inx h
mvi m,' '
dcr b
jnz padname
;
setty: ;set the type field
mvi b,3
cpi '.'
jnz padty ;skip the field if not there
inx d ;past the '.', to the type field
;
setty0: ;set the field from the command buffer
call delim
jz padty
inx h
cpi '*'
jnz setty1 ;[only 'se' on listing]-
mvi m,'?' ;since * specified
jmp setty2
;
setty1: ;not a * so copy to type field
mov m,a
inx d
;
setty2: dcr b
jnz setty0
;
;end of type field, truncate
trtyp: ;truncate type field
call delim
jz efill
inx d
jmp trtyp
;
padty: ;pad the type field with blanks
inx h
mvi m,' '
dcr b
jnz padty
;
efill: ;end of filename/filetype fill, save command
; address, fill the remaining fields for the
; fcb
mvi b,3
;
efill0:
inx h
mvi m,0
dcr b
jnz efill0
xchg
shld comaddr ;set new starting point
;
;recover the start address of the fcb and
;count ?'s
pop h
lxi b,11 ;b=0, c=8+3
;
scnq: inx h
mov a,m
cpi '?'
jnz scnq0 ;? found, count it in b
inr b
;
scnq0: dcr c
jnz scnq
;
;number of ?'s in c [sic], move to a and
mov a,b ;return with flags set
ora a
ret
;
intvec: ;intrinsic function names (all are four
db 'DIR ' ; characters)
db 'ERA '
db 'TYPE'
db 'SAVE'
db 'REN '
db 'USER'
;
intlen equ ($-intvec)/4 ;intrinsic function length
;
serial: db 0,0,0,0,0,0
;
intrinsic: ;look for intrinsic functions (comfcb has
; been filled
lxi h,intvec
mvi c,0 ;c counts intrinsics as scanned
;
intrin0:
mov a,c
cpi intlen ;done with scan?
rnc
lxi d,comfcb+1 ;beginning of name
mvi b,4 ;length of match is in b
;
intrin1:
ldax d
cmp m ;match
jnz intrin2 ;skip if no match
inx d
inx h
dcr b
jnz intrin1 ;loop while matching
;
;complete match on name, check for blank in fcb
ldax d
cpi ' '
jnz intrin3 ;otherwise matched
mov a,c
ret ;with intrinsic number in a
;
intrin2: ;mismatch, move to end of intrinsic
inx h
dcr b
jnz intrin2
;
intrin3: ;try next intrinsic
inr c ;to next intrinsic number
jmp intrin0 ;for another round
;
ccpclear: ;clear the command buffer
xra a
sta comlen ;drop through to start ccp
;
ccpstart: ;enter here from boot loader
lxi sp,stack
push b ;save initial disk number
;(high order 4 bits = user code, low order
;4 bits = disk #)
mov a,c
rar
rar
rar
rar
ani 0fh ;user code
mov e,a
call setuser ;user code selected
;initialize for this user, get $ flag
call initialize ;0ffh in accum if $ present
sta submit ;submit flag set if $ file present
pop b ;recall user code and disk number
mov a,c
ani 0fh ;disk number in accumulator
sta cdisk ;clears user code nibble
call select ;proper disk is selected, now check sub file
;check for initial command
lda comlen
ora a
jnz ccp0 ;assumed typed already
;
ccp: ;enter here on each command or error condition
lxi sp,stack
call crlf ;print D> where d is disk number
call cselect
adi 'A'
call printchar
mvi a,'>'
call printchar
call readcom ;command buffer filled
;
ccp0: ;(enter here from initialization with command
; filled)
lxi d,buff
call setdma ;default dma address at buff
call cselect
sta cdisk ;current disk number saved
call fillfcb0 ;command fcb filled
cnz comerr ;the name cannot be an ambiguous reference
lda sdisk
ora a
jnz userfunc ;check for an intrinsic function
;
call intrinsic
lxi h,jmptab ;index is in the accumulator
mov e,a
mvi d,0
dad d
dad d ;index in d,e
mov a,m
inx h
mov h,m
mov l,a
pchl ;pc changes to the proper intrinsic or user
;function
jmptab:
dw direct ;directory search
dw erase ;file erase
dw type ;type
dw save ;save memory
dw rename ;file rename
dw user ;user number
dw userfunc ;user-defined function
;
badserial:
lxi h,di or (hlt shl 8)
shld ccploc
lxi h,ccploc
pchl
;
;utility subroutines for intrinsic handlers
;
readerr: ;print the read error message
lxi b,rdmsg
jmp print
;
rdmsg: db 'read error',0
;
nofile: ;print no file message
lxi b,nofmsg
jmp print
;
nofmsg: db 'no file',0
;
getnumber: ;read a number from the command line
call fillfcb0 ;should be a number
lda sdisk
ora a
jnz comerr ;cannot be prefixed
;convert the byte value in comfcb to binary
lxi h,comfcb+1
lxi b,11 ;(b = 0, c = 11)
;value accumulated in b, c counts name length
; to zero
conv0: mov a,m
cpi ' '
jz conv1 ;more to scan
;
inx h
sui '0'
cpi 10
jnc comerr ;valid?
mov d,a
mov a,b ;multiply by ten
ani 1110$0000b
jnz comerr
mov a,b
rlc
rlc
rlc ;*8
add b
jc comerr
add b
jc comerr ;*8 + *2 = *10
add d
jc comerr ;+digit
mov b,a
dcr c
jnz conv0 ;for another digit
ret
;
conv1: ;end of digits, check for all blanks
mov a,m
cpi ' '
jnz comerr ;blanks?
inx h
dcr c
jnz conv1
mov a,b ;recover value
ret
;
movename: ;move 3 characters from h,l to d,e addresses
;
mvi b,3
;
move0: mov a,m
stax d
inx h
inx d
dcr b
jnz move0
ret
;
addhcf: ;buff + a + c to h,l followed by fetch
lxi h,buff
add c
call addh
mov a,m
ret
;
setdisk:
;change disks for this command, if requested
xra a
sta comfcb ;clear disk name from fcb
lda sdisk
ora a
rz ;no action if not specified
dcr a
lxi h,cdisk
cmp m
rz ;already selected
jmp select
;
resetdisk:
;return to original disk after command
lda sdisk
ora a
rz ;no action if not selected
dcr a
lxi h,cdisk
cmp m
rz ;same disk
lda cdisk
jmp select
;
;individual intrinsics follow
direct:
;directory search
call fillfcb0 ;comfcb gets file name
call setdisk ;change disk drives if requested
lxi h,comfcb+1
mov a,m ;may be empty request
cpi ' '
jnz dir1 ;skip fill of ??? if not blank
;set comfcb to all ??? for current disk
mvi b,11 ;length of fill ????????.???
dir0:
mvi m,'?'
inx h
dcr b
jnz dir0
;not a blank request, must be in comfcb
dir1:
mvi e,0
push d ;e counts directory entries
call searchcom ;first one has been found
cz nofile ;not found message
dir2:
jz endir
;found, but may be system file
lda dcnt ;get the location of the element
rrc
rrc
rrc
ani 110$0000b
mov c,a ;c contains base index into buff for dir entry
mvi a,sysfile
call addhcf ;value to a
ral
jc dir6 ;skip if system file
;c holds index into buffer
;another fcb found, new line?
pop d
mov a,e
inr e
push d
;e=0,1,2,3,...new line if mod 4 = 0
ani 11b
push psw ;and save the test
jnz dirhdr0 ;header on current line
call crlf
push b
call cselect
pop b
;current disk in a
adi 'A'
call printbc
mvi a,':'
call printbc
jmp dirhdr1 ;skip current line hdr
;
dirhdr0:
call blank ;after last one
mvi a,':'
call printbc
;
dirhdr1:
call blank ;compute position of name in buffer
mvi b,1 ;start with first character of name
;
dir3:
mov a,b
call addhcf ;buff+a+c fetched
ani 7FH ;mask flags
;may delete trailing blanks
cpi ' '
jnz dir4 ;check for blank type
pop psw
push psw ;may be 3rd item
cpi 3
jnz dirb ;place blank at end if not
mvi a,9
call addhcf ;first char of type
ani 7fh
cpi ' '
jz dir5 ;not a blank in the file type field
;
dirb: mvi a,' ' ;restore trailing filename chr
dir4:
call printbc ;char printed
inr b
mov a,b
cpi 12
jnc dir5 ;check for break between names
cpi 9
jnz dir3 ;for another char
;print a blank between names
call blank
jmp dir3
;
dir5: ;end of current entry
pop psw ;discard the directory counter (mod 4)
dir6: call break$key
;check for interrupt at keyboard
jnz endir ;abort directory search
call searchn
jmp dir2 ;for another entry
;
endir: ;end of directory scan
pop d ;discard directory counter
jmp retcom
;
;
erase:
call fillfcb0 ;cannot be all ???'s
cpi 11
jnz erasefile
;erasing all of the disk
lxi b,ermsg
call print
call readcom
lxi h,comlen
dcr m
jnz ccp ;pad input
inx h
mov a,m
cpi 'Y'
jnz ccp
;ok, erase the entire diskette
inx h
shld comaddr ;otherwise error at retcom
;
erasefile:
call setdisk
lxi d,comfcb
call delete
inr a ;255 returned in not found
cz nofile ;no file message if so
jmp retcom
;
;
ermsg: db 'All (Y/N)?',0
;
type:
call fillfcb0
jnz comerr ;don't allow ?'s in file name
call setdisk
call openc ;open the file
jz typerr ;zero flag indicates not found
;file opened, real 'til eof
call crlf
lxi h,bptr
mvi m,255 ;read first buffer
;
type0: ;loop on bptr
lxi h,bptr
mov a,m
cpi 128 ;end buffer
jc type1
push h ;carry 1f 0,1,...,127
;read another buffer full
call diskreadc
pop h ;recover address of bp
jnz typeof ;hard end of file
xra a
mov m,a ;bptr = 0
;
type1: ;read character at bptr and print
inr m ;bptr = bptr + 1
lxi h,buff
call addh ;h,l addresses char
mov a,m
cpi eofile
jz retcom
call printchar
call break$key
jnz retcom ;abort if break
jmp type0 ;for another character
;
typeof: ;end of file, check for errors
dcr a
jz retcom
call readerr
;
typerr: call resetdisk
jmp comerr
;
save:
call getnumber ;value to register a push
push psw ;save it for later
;should be followed by a flip
;to save the memory ima
call fillfcb0
jnz comerr ;cannot be ambiguous
call setdisk ;may be a disk change
lxi d,comfcb
push d
call delete ;existing file rem
pop d
call make ;create a new file on disk
jz saverr ;no directory space
xra a
sta comrec ;clear next record field
pop psw ;#pages to write is in a, change to #sectors
mov l,a
mvi h,0
dad h
lxi d,tran ;h,l is sector count, d,e is load address
;
save0: ;check for sector count zero
mov a,h
ora l
jz save1 ;may be completed
dcx h ;sector count = sector count - 1
push h ;save it for next time around
lxi h,128
dad d
push h ;next dma address saved
call setdma ;current dma address set
lxi d,comfcb
call diskwrite
pop d
pop h ;dma address, sector count
jnz saverr ;may be disk full case
jmp save0 ;for another sector
;
save1: ;end of dump, close the file
lxi d,comfcb
call close
inr a ;255 becomes 00 if error
jnz retsave ;for another command
;
saverr: ;must be full or head only disk
lxi b,fullmsg
call print
;
retsave:
;reset dma buffer
call setdmabuff
jmp retcom
;
fullmsg:
db 'no space',0
;
;
rename: ;rename a file on a specific disk
call fillfcb0
jnz comerr ;must be unambiguous
lda sdisk
push psw ;save for later compare
call setdisk ;disk selected
call searchcom ;is new name already there?
jnz renerr3 ;file doesn't exist, move to second half of fcb
lxi h,comfcb
lxi d,comfcb+16
mvi b,16
call move0 ;check for = or left arrow
lhld comaddr
xchg
call deblank
cpi '='
jz ren1
cpi la
jnz renerr2
;
ren1: xchg
inx h
shld comaddr ;past delimiter
;proper delimiter found
call fillfcb0
jnz renerr2
;check for dirve conflict
pop psw
mov b,a ;previous drive number
lxi h,sdisk
mov a,m
ora a
jz ren2
;drive name was specified. same one?
cmp b
mov m,b
jnz renerr2
;
ren2: mov m,b ;store the name in case drives switched
xra a
sta comfcb
call searchcom
;is old file there
jz renerr1
;everything is ok, rename the file
lxi d,comfcb
call renam
jmp retcom
;
renerr1: ;no file on disk
call nofile
jmp retcom
;
renerr2: ;ambigous reference/name conflict
call resetdisk
jmp comerr
;
renerr3: ;file already exists
lxi b,renmsg
call print
jmp retcom
;
renmsg: db 'file exists',0
;
user:
;set user number
call getnumber ;leaves the value in the accumulator
cpi 16
jnc comerr ;must be between 0 and 15
mov e,a ;save for setuser call
lda comfcb+1
cpi ' '
jz comerr
call setuser ;new user number set
jmp endcom
;
userfunc:
call serialize
;check serialization
;load user function and set up for execution
lda comfcb+1
cpi ' '
jnz user0
;no file name, but may be disk switch
lda sdisk
ora a
jz endcom ;no disk name if 0
dcr a
sta cdisk
call setdiska ;set user/disk
call select
jmp endcom
;
user0: ;file name is present
lxi d,comfcb+9
ldax d
cpi ' '
jnz comerr ;type '
push d
call setdisk
pop d
lxi h,comtype ;.com
call movename
;file type is set to .com
call openc
jz userer
;file opened properly, read it into memory
lxi h,tran ;transient program base
;
load0:
push h ;save dma address
xchg
call setdma
lxi d,comfcb
call diskread
jnz load1
;sector loaded, set new dma address and com
pop h
lxi d,128
dad d
lxi d,tranm ;has the load overflowed?
mov a,l
sub e
mov a,h
sbb d
jnc loaderr
jmp load0 ;for another sector
;
load1: pop h
dcr a
jnz loaderr ;end file is 1
call resetdisk ;back to original disk
call fillfcb0
lxi h,sdisk
push h
mov a,m
sta comfcb ;drive number set
mvi a,16
call fillfcb ;move entire fct to
pop h
mov a,m
sta comfcb+16
xra a
sta comrec ;record number set to zero
lxi d,fcb
lxi h,comfcb
mvi b,33
call move0 ;move command line to buff
lxi h,combuf
;
bmove0: mov a,m
ora a
jz bmove1
cpi ' '
jz bmove1 ;[text was truncated, I made it 1] -
inx h
jmp bmove0 ;for another scan
;first blank position found
bmove1: mvi b,0
lxi d,buff+1
;ready for the move
bmove2: mov a,m
stax d
ora a
jz bmove3 ;more to move
inr b
inx h
inx d
jmp bmove2
;
bmove3: ;b has character count
mov a,b
sta buff
call crlf
;now go to the loaded program
call setdmabuff
;default dma
call saveuser
;user code saved
;low memory diska contains user code
call tran ;gone to the loaded program
lxi sp,stack
;may come back here
call setdiska
call select
jmp ccp
;
userer: ;arrive here on command error
call resetdisk
jmp comerr
;
loaderr: ;cannot load the program
lxi b,loadmsg
call print
jmp retcom
;
loadmsg:
db 'bad load',0
;
comtype:
db 'com' ;for com files
;
;
retcom: ;reset disk before end of command check
call resetdisk
;
endcom: ;end of intrinsic command
call fillfcb0
;to check for garbage at end of line
lda comfcb+1
sui ' '
lxi h,sdisk
ora m ;0 in accumulator if no disk selected,
;and blank fcb
jnz comerr
jmp ccp
;
;
; data areas
;
ds 16 ;8 level stack
stack:
;
; 'submit' fiel control block
;
submit: db 0 ;00 if no submit file, ff if submitting
subfcb: db 0,'$$$ ' ;file name is $$$
db 'sub',0,0 ;file name is sub
submod: db 0 ;module number
subrc: ds 1 ;record count filed
ds 16 ;disk map
subcr: ds 1 ;current record to read
;
; command file control block
;
comfcb: ds 32 ;fields filled in later
comrec: ds 1 ;current record to read/write
dcnt: ds 1 ;disk directory count (used for error codes)
cdisk: ds 1 ;current disk
sdisk: ds 1 ;selected disk for current operation
;none=0, a=1, b=2 ...
bptr: ds 1 ;buffer pointer
;
end ccploc