title Console Command Processor (ccp), ver 2.0 ; assembly language version of the cp/m console command processor ; ; Personal CP/M version 1.0 May 1984 ; ; COPYRIGHT (C) 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984 ; Digital Research ; Box 579, Pacific Grove, ; California, 93950 ; false equ 0000h true equ not false ; ; cseg BASE equ $ BDOSL equ BASE+800H SUBADDR equ BDOSL+09H ZEROADD equ BDOSL+0BH 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 * ; * the 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. * ; ******************************************************** jp ccpstart ;start ccp with possible initial command jp ccpclear ;clear the command buffer maxlen: defb 127 ;max buffer length comlen: defb 6 ;command length combuf: defb 'VCCPLD ' ;8 character fill defb ' ' ;8 character fill defb 'COPYRIGHT (C) 1984, DIGITAL RESEARCH ' ; 38 defs 128-($-combuf) ;total buffer length is 128 characters comaddr: defw combuf ;address of next to char to scan staddr: defs 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 currently 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: ld E,A ld C,pcharf jp bdos printbc: ;print character, but save b,c registers push bc call printchar pop bc ret crlf: ld A,cr call printbc ld A,lf jr printbc blank: ld A,' ' jr printbc Šprint: ;print string starting at b,c until next 00 entry push bc call crlf pop hl ;now print the string prin0: ld A,(hl) or A ret z ;stop on 00 inc hl push hl ;ready for next call printchar pop hl ;character printed jr prin0 ;for another character initialize: ld C,initf jp bdos select: ld E,A ld C,self jp bdos openc: ;open comfcb xor A ld (comrec),a ;clear next record to read ld de,comfcb open: ;open the file given by d,e ld C,openf bdos$inr: call bdos ld (dcnt),a inc A ret close: ;close the file given by d,e ld C,closef jr bdos$inr search: ;search for the file given by d,e ld C,searf jr bdos$inr searchn: ;search for the next occurrence of the file given by d,e ld C,searnf jr bdos$inr searchcom: ;search for comfcb file ld de,comfcb jr search delete: ;delete the file given by d,e ld C,delf jp bdos bdos$cond: call bdos or A ret diskread: ;read the next record from the file given by d,e ld C,dreadf jr bdos$cond diskreadc: ;read the comfcb file ld de,comfcb jr diskread diskwrite: ;write the next record to the file given by d,e ld C,dwritf jr bdos$cond Šmake: ;create the file given by d,e ld C,makef jr bdos$inr renam: ;rename the file given by d,e ld C,renf jp bdos getuser: ;return current user code in a ld E,0ffh ;drop through to setuser setuser: ld (USERNO),a ld C,userf jp bdos ;sets user number saveuser: ;save user#/disk# before possible ^c or transient call GETUSER ld (USERNO),a add a,A add a,A add a,A add a,A ;rot left ld hl,cdisk or (hl) ;4b=user, 4b=disk ld (diska),a ;stored away in memory for later ret translate: ;translate character in register a to upper case cp 61h ret c ;return if below lower case a cp 7bh ret nc ;return if above lower case z and 5fh ret ;translated to upper case COPY$SUBFCB: ld hl,(SUBADDR) inc hl ld de,SUB$S1 ld B,21 or A jr nz,COPY$SF1 ex de,hl COPY$SF1: dec B ret z ld A,(hl) ld (de),a inc hl inc de jr COPY$SF1 readcom: ;read the next command into the command buffer ;check for submit file ld hl,(SUBADDR) ld A,(hl) or A jr z,NOSUB inc A jr z,OPEN$SUB call COPY$SUBFCB jr READ$SUB OPEN$SUB: push hl ld de,SUBFCB call OPEN pop hl ld (hl),0 jr z,NOSUB inc (hl) READ$SUB: call SETDMABUFF ;change drives to open and read the file ld a,(subrc) dec A ;read last record(s) first ld (subcr),a ;current record to read ld de,subfcb call diskread ;end of file if last record jr nz,nosub Š;disk read is ok, transfer to combuf ld de,comlen ld hl,buff ld B,128 call move0 ;line is transferred, close the file with a ;deleted record ld hl,SUBRC dec (hl) ; ONE LESS RECORD xor A call COPY$SUBFCB ;print to the 00 ld hl,combuf call prin0 call break$key jr z,noread call del$sub jp ccp ;break key depressed nosub: ;no submit file call del$sub ;translate to upper case, store zero at end call saveuser ;user # save in case control c ld hl,(SUBADDR) dec hl ld (hl),0FFH push hl ld C,rbuff ld de,maxlen call bdos pop hl ld (hl),0 noread: ;enter here from submit file ;set the last character to zero for later scans ld hl,comlen ld B,(hl) ;length is in b readcom0: inc hl ld A,B or A ;end of scan? jr z,readcom1 ld A,(hl) ;get character and translate call translate ld (hl),A dec B jr readcom0 readcom1: ;end of scan, h,l address end of command ld (hl),A ;store a zero ld hl,combuf ld (comaddr),hl ;ready to scan to zero ret break$key: ;check for a character ready at the console ld C,breakf call bdos or A ret z ld C,rcharf call bdos ;character cleared or A ret cselect: ;get the currently selected drive number to reg-a ld C,cself jp bdos setdmabuff: ;set default buffer dma address ld de,buff ;(drop through) setdma: ;set dma address to d,e ld C,dmaf jp bdos del$sub: ;delete the submit file, and set submit flag to false ld hl,(SUBADDR) ld A,(hl) or A ret z ;return if no sub file ld (hl),0 ;submit flag is set to false ld de,subfcb jp delete comerr: ;error in command string starting at position ;'staddr' and ending with first delimiter call crlf ;space to next line ld hl,(staddr) ;h,l address first to print comerr0: ;print characters until blank or zero ld A,(hl) cp ' ' jr z,comerr1 ; not blank or A jr z,comerr1 ; not zero, so print it push hl call printchar pop hl inc hl jr comerr0 ; for another character comerr1: ;print question mark,and delete sub file ld A,'?' call printchar call crlf call del$sub jp 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 delimiter ld a,(de) or A ret z ;not the last element cp ' ' jr c,comerr ;non graphic ret z ;treat blank as delimiter cp '=' ret z cp la ret z ;left arrow cp '.' ret z cp ':' ret z cp ';' ret z cp '<' ret z cp '>' ret z ret ;delimiter not found deblank: ;deblank the input line ld a,(de) or A ret z ;treat end of line as blank cp ' ' ret nz inc de jr deblank addh: ;add a to h,l add a,L ld L,A ret nc inc H ret fillfcb0: ;equivalent to fillfcb(0) ld A,0 fillfcb: ld hl,comfcb call addh push hl push hl ;fcb rescanned at end xor A ld (sdisk),a ;clear selected disk (in case a:...) ld hl,(comaddr) ex de,hl ;command address in d,e call deblank ;to first non-blank character ex de,hl ld (staddr),hl ;in case of errors ex de,hl pop hl ;d,e has command, h,l has fcb address ;look for preceding file name a: b: ... ld a,(de) or A jr z,setcur0 ;use current disk if empty command sbc a,'A'-1 ld B,A ;disk name held in b if : follows inc de ld a,(de) cp ':' jr z,setdsk ;set disk name if : setcur: ;set current disk Š dec de ;back to first character of command setcur0: ld a,(cdisk) ld (hl),A jr setname setdsk: ;set disk to name in register b ld A,B ld (sdisk),a ;mark as disk selected ld (hl),B inc de ;past the : setname: ;set the file name field ld B,8 ;file name length (max) setnam0: call delim jr z,padname ;not a delimiter inc hl cp '*' jr nz,setnam1 ;must be ?'s ld (hl),'?' jr setnam2 ;to dec count setnam1: ld (hl),A ;store character to fcb inc de setnam2: dec B ;count down length jr nz,setnam0 ;end of name, truncate remainder trname: call delim jr z,setty ;set type field if delimiter inc de jr trname padname: inc hl ld (hl),' ' dec B jr nz,padname setty: ;set the type field ld B,3 cp '.' jr nz,padty ;skip the type field if no . inc de ;past the ., to the file type field setty0: ;set the field from the command buffer call delim jr z,padty inc hl cp '*' jr nz,setty1 ld (hl),'?' ;since * specified jr setty2 setty1: ;not a *, so copy to type field ld (hl),A inc de setty2: ;decrement count and go again dec B jr nz,setty0 ;end of type field, truncate trtyp: ;truncate type field call delim jr z,efill inc de jr trtyp padty: ;pad the type field with blanks inc hl ld (hl),' ' dec B jr nz,padty efill: ;end of the filename/filetype fill, save command address ;fill the remaining fields for the fcb ld B,3 efill0: inc hl ld (hl),0 dec B jr nz,efill0 ex de,hl ld (comaddr),hl ;set new starting point ;recover the start address of the fcb and count ?'s pop hl ld bc,11 ;b=0, c=8+3 scnq: inc hl ld A,(hl) cp '?' jr nz,scnq0 ;? found, count it in b inc B scnq0: dec C jr nz,scnq ;number of ?'s in c, move to a and return with flags set Š ld A,B or A ret intvec: ;intrinsic function names (all are four characters) defb 'DIR ' defb 'ERA ' defb 'TYPE' defb 'SAVE' defb 'REN ' defb 'USER' intlen equ ($-intvec)/4 ;intrinsic function length intrinsic: ;look for intrinsic functions (comfcb has been filled) ld hl,intvec ld C,0 ;c counts intrinsics as scanned intrin0: lä A,C cp intlen ;done with scan? ret nc ;no, more to scan ld de,comfcb+1 ;beginning of name ld B,4 ;length of match is in b intrin1: ld a,(de) cp (hl) ;match? jr nz,intrin2 ;skip if no match inc de inc hl dec B jr nz,intrin1 ;loop while matching ;complete match on name, check for blank in fcb ld a,(de) cp ' ' jr nz,intrin3 ;otherwise matched ld A,C ret ;with intrinsic number in a intrin2: ;mismatch, move to end of intrinsic inc hl dec B jr nz,intrin2 intrin3: ;try next intrinsic inc C ;to next intrinsic number jr intrin0 ;for another round ccpclear: ;clear the command buffer xor A ld (comlen),a ;drop through to start ccp ccpstart: ;enter here from boot loader ld sp,stack push bc ;save initial disk number ;(high order 4bits=user code, low 4bits=disk#) ld A,C rra rra rra rra and 0fh ;user code ld E,A call setuser ;user code selected ld hl,(SUBADDR) dec hl ld A,(hl) ld (hl),0 or A call nz,INITIALIZE pop bc ;recall user code and disk number ld A,C and 0fh ;disk number in accumulator ld (cdisk),a ;clears user code nibble call select ;proper disk is selected, now check sub files ;check for initial command ld a,(comlen) or A jr nz,ccp0 ;assume typed already Šccp: ;enter here on each command or error condition ld sp,stack call crlf ;print d> prompt, where d is disk name ld a,(USERNO) or A jr z,CCP002 cp 10 jr c,CCP001 push af ld A,'1' call PRINTCHAR pop af sub 10 CCP001: add a,30H call PRINTCHAR CCP002: call cselect ;get current disk number add a,'A' call printchar ld A,'>' call printchar call readcom ;command buffer filled ccp0: ;(enter here from initialization with command full) call SETDMABUFF ;default dma address at buff call cselect ld (cdisk),a ;current disk number saved call fillfcb0 ;command fcb filled call nz,comerr ;the name cannot be an ambiguous reference ld a,(sdisk) or A jp nz,userfunc ;check for an intrinsic function call intrinsic ld hl,jmptab ;index is in the accumulator ld E,A ld D,0 add hl,de add hl,de ;index in d,e ld A,(hl) inc hl ld H,(hl) ld L,A jp (hl) ;pc changes to the proper intrinsic or user function jmptab: defw direct ;directory search defw erase ;file erase defw type ;type file defw save ;save memory image defw rename ;file rename defw user ;user number defw userfunc ;user-defined function ; ;utility subroutines for intrinsic handlers ; readerr: ;print the read error message ld bc,rdmsg jp print rdmsg: defb 'READ ERROR',0 nofile: ;print no file message ld bc,nofmsg jp print nofmsg: defb 'NO FILE',0 getnumber: ;read a number from the command line call fillfcb0 ;should be number ld a,(sdisk) or A jp nz,comerr ;cannot be prefixed ;convert the byte value in comfcb to binary ld hl,comfcb+1 ld bc,11 ;(b=0, c=11) ;value accumulated in b, c counts name length to zero conv0: ld A,(hl) cp ' ' jr z,conv1 Š;more to scan, convert char to binary and add inc hl sub '0' cp 10 jp nc,comerr ;valid? ld D,A ;save value ld A,B ;mult by 10 and 11100000b jp nz,comerr ld A,B ;recover value rlca rlca rlca ;*8 add a,B jp c,comerr add a,B jp c,comerr ;*8+*2 = *10 add a,D jp c,comerr ;+digit ld B,A dec C jr nz,conv0 ;for another digit ret conv1: ;end of digits, check for all blanks ld A,(hl) cp ' ' jp nz,comerr ;blanks? inc hl dec C jr nz,conv1 ld A,B ;recover value ret movename: ;move 3 characters from h,l to d,e addresses ld B,3 move0: ld A,(hl) ld (de),a inc hl inc de dec B jr nz,move0 ret addhcf: ;buff + a + c to h,l followed by fetch ld hl,buff add a,C call addh ld A,(hl) ret setdisk: ;change disks for this command, if requested xor A ld (comfcb),a ;clear disk name from fcb ld a,(sdisk) or A ret z ;no action if not specified dec A ld hl,cdisk cp (hl) ret z ;already selected jp select resetdisk: ;return to original disk after command ld a,(sdisk) or A ret z ;no action if not selected dec A ld hl,cdisk cp (hl) ret z ;same disk ld a,(cdisk) jp select ; ;individual intrinsics follow ; direct: ;directory search call fillfcb0 ;comfcb gets file name call setdisk ;change disk drives if requested ld hl,comfcb+1 ld A,(hl) ;may be empty request cp ' ' jr nz,dir1 ;skip fill of ??? if not blank ;set comfcb to all ??? for current disk ld B,11 ;length of fill ????????.??? dir0: ld (hl),'?' inc hl dec B jr nz,dir0 ;not a blank request, must be in comfcb dir1: lä E,0 push de ;e counts directory entries call searchcom ;first one has been found call z,nofile ;not found message dir2: jr z,endir ;found, but may be system file Š ld a,(dcnt) ;get the location of the element rrca rrca rrca and 1100000b ld C,A ;c contains base index into buff for dir entry ld A,sysfile call addhcf ;value to a rla jr c,dir6 ;skip if system file ;c holds index into buffer ;another fcb found, new line? pop de ld A,E inc E push de ;e=0,1,2,3,...new line if mod 4 = 0 and 11b push af ;and save the test jr nz,dirhdr0 ;header on current line call crlf push bc call cselect pop bc ;current disk in a add a,'A' call printbc ld A,':' call printbc jr dirhdr1 ;skip current line hdr dirhdr0: call blank ;after last one ld A,':' call printbc dirhdr1: call blank ;compute position of name in buffer ld B,1 ;start with first character of name dir3: ld A,B call addhcf ;buff+a+c fetched and 7fh ;mask flags ;may delete trailing blanks cp ' ' jr nz,dir4 ;check for blank type pop af push af ;may be 3rd item cp 3 jr nz,dirb ;place blank at end if not ld A,9 call addhcf ;first char of type and 7fh cp ' ' jr z,dir5 ;not a blank in the file type field dirb: ld A,' ' ;restore trailing filename chr dir4: call printbc ;char printed inc B ld A,B cp 12 jr nc,dir5 ;check for break between names cp 9 jr nz,dir3 ;for another char ;print a blank between names call blank jr dir3 dir5: ;end of current entry pop af ;discard the directory counter (mod 4) dir6: call break$key ;check for interrupt at keyboard jr nz,endir ;abort directory search call searchn jr dir2 ;for another entry endir: ;end of directory scan pop de ;discard directory counter jp retcom erase: call fillfcb0 ;cannot be all ???'s cp 11 jr nz,erasefile Š;erasing all of the disk ld bc,ermsg call print call readcom ld hl,comlen dec (hl) jp nz,ccp ;bad input inc hl ld A,(hl) cp 'Y' jp nz,ccp ;ok, erase the entire diskette inc hl ld (comaddr),hl ;otherwise error at retcom erasefile: call setdisk ld de,comfcb call delete inc A ;255 returned if not found call z,nofile ;no file message if so jp retcom ermsg: defb 'ALL (Y/N)?',0 type: call fillfcb0 jp nz,comerr ;don't allow ?'s in file name call setdisk call openc ;open the file jr z,typerr ;zero flag indicates not found ;file opened, read 'til eof call crlf ld hl,bptr ld (hl),255 ;read first buffer type0: ;loop on bptr ld hl,bptr ld A,(hl) cp 128 ;end buffer jr c,type1 push hl ;carry if 0,1,...,127 ;read another buffer full call diskreadc pop hl ;recover address of bptr jr nz,typeof ;hard end of file xor A ld (hl),A ;bptr = 0 type1: ;read character at bptr and print inc (hl) ;bptr = bptr + 1 ld hl,buff call addh ;h,l addresses char ld A,(hl) cp eofile jp z,retcom call printchar call break$key jp nz,retcom ;abort if break jr type0 ;for another character typeof: ;end of file, check for errors dec A jp z,retcom call readerr typerr: call resetdisk jp comerr save: call getnumber ; value to register a push af ;save it for later ;should be followed by a file to save the memory image call fillfcb0 jp nz,comerr ;cannot be ambiguous call setdisk ;may be a disk change ld de,comfcb push de call delete ;existing file removed pop de call make ;create a new file on disk jr z,saverr ;no directory space xor A ld (comrec),a ; clear next record field pop af ;#pages to write is in a, change to #sectors Š ld L,A ld H,0 add hl,hl ld de,tran ;h,l is sector count, d,e is load address save0: ;check for sector count zero ld A,H or L jr z,save1 ;may be completed dec hl ;sector count = sector count - 1 push hl ;save it for next time around ld hl,128 add hl,de push hl ;next dma address saved call setdma ;current dma address set ld de,comfcb call diskwrite pop de pop hl ;dma address, sector count jr nz,saverr ;may be disk full case jr save0 ;for another sector save1: ;end of dump, close the file ld de,comfcb call close inc A ; 255 becomes 00 if error jr nz,retsave ;for another command saverr: ;must be full or read only disk ld bc,fullmsg call print retsave: ;reset dma buffer call setdmabuff jp retcom fullmsg: defb 'NO SPACE',0 rename: ;rename a file on a specific disk call fillfcb0 jp nz,comerr ;must be unambiguous ld a,(sdisk) push af ;save for later compare call setdisk ;disk selected call searchcom ;is new name already there? jr nz,renerr3 ;file doesn't exist, move to second half of fcb ld hl,comfcb ld de,comfcb+16 ld B,16 call move0 ;check for = or left arrow ld hl,(comaddr) ex de,hl call deblank cp '=' jr z,ren1 ;ok if = cp la jr nz,renerr2 ren1: ex de,hl inc hl ld (comaddr),hl ;past delimiter ;proper delimiter found call fillfcb0 jr nz,renerr2 ;check for drive conflict pop af ld B,A ;previous drive number ld hl,sdisk ld A,(hl) or A jr z,ren2 ;drive name was specified. same one? cp B ld (hl),B jr nz,renerr2 ren2: ld (hl),B ;store the name in case drives switched xor A ld (comfcb),a call searchcom ;is old file there? jr z,renerr1 ;everything is ok, rename the file ld de,comfcb call renam jp retcom renerr1: ; no file on disk call nofile jp retcom renerr2: ; ambigous reference/name conflict call resetdisk jp comerr renerr3: ; file already exists ld bc,renmsg call print jp retcom renmsg: defb 'FILE EXISTS',0 user: ;set user number call getnumber ; leaves the value in the accumulator cp 16 jp nc,comerr ; must be between 0 and 15 ld E,A ;save for setuser call ld a,(comfcb+1) cp ' ' jp z,comerr ld A,E call setuser ;new user number set jp endcom userfunc: ;load user function and set up for execution ld a,(comfcb+1) cp ' ' jr nz,user0 ;no file name, but may be disk switch ld a,(sdisk) or A jp z,endcom ;no disk name if 0 dec A ld (cdisk),a ;set user/disk call select jp endcom user0: ;file name is present ld de,comfcb+9 ld a,(de) cp ' ' jp nz,comerr ;type ' ' push de call setdisk pop de ld hl,comtype ;.com call movename ;file type is set to .com call openc jp z,userer ;file opened properly, read it into memory ld hl,tran ;transient program base load0: push hl ;save dma address ex de,hl call setdma ld de,comfcb call diskread jr nz,load1 ;sector loaded, set new dma address and compare pop hl ld de,128 add hl,de ld de,tranm ;has the load overflowed? ld A,L sub E ld A,H sbc a,D jr nc,loaderr jr load0 ;for another sector load1: pop hl dec A jr nz,loaderr ;end file is 1 call resetdisk ;back to original disk call fillfcb0 ld hl,sdisk push hl ld A,(hl) ld (comfcb),a ;drive number set ld A,16 call fillfcb ;move entire fcb to memory pop hl ld A,(hl) ld (comfcb+16),a xor A ld (comrec),a ;record number set to zero ld de,fcb ld hl,comfcb ld B,33 call move0 ;move command line to buff ld hl,combuf bmove0: ld A,(hl) or A jr z,bmove1 cp ' ' jr z,bmove1 inc hl jr bmove0 ;for another scan ;first blank position found bmove1: ld B,0 ld de,buff+1 ;ready for the move bmove2: ld A,(hl) ld (de),a or A jr z,bmove3 Š;more to move inc B inc hl inc de jr bmove2 bmove3: ;b has character count ld A,B ld (buff),a call crlf ;now go to the loaded program call setdmabuff ;default dma call saveuser ;user code saved ld hl,(ZEROADD) ld C,4 ZMOVE: ld (hl),0 inc hl dec C jr nz,ZMOVE ;low memory diska contains user code call tran ;gone to the loaded program ld sp,stack ;may come back here ld a,(USERNO) ld E,A call SETUSER ld a,(CDISK) call select jp ccp userer: ;arrive here on command error call resetdisk jp comerr loaderr: ;cannot load the program ld bc,loadmsg call print jr retcom loadmsg: defb 'BAD LOAD',0 comtype: defb '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 ld a,(comfcb+1) sub ' ' ld hl,sdisk or (hl) ;0 in accumulator if no disk selected, and blank fcb jp nz,comerr jp ccp ; ; data areas ; defs 16 ;8 level stack stack: ; ; 'submit' file control block ; subfcb: defb 1,'$$$ ' ;file name is $$$ defb 'SUB',0 sub$s1: defb 0 ;file type is sub submod: defb 0 ;module number subrc: defs 1 ;record count filed defs 16 ;disk map subcr: defs 1 ;current record to read ; ; command file control block ; Šcomfcb: defs 32 ;fields filled in later comrec: defs 1 ;current record to read/write dcnt: defs 1 ;disk directory count (used for error codes) cdisk: defs 1 ;current disk sdisk: defs 1 ;selected disk for current operation ;none=0, a=1, b=2 ... USERNO: defs 1 ;CURRENT USER NUMBER bptr: defs 1 ;buffer pointer ; this is code tto make the BDOS (which follows) be on a ; 256 byte page boundry. (make the linker happy) last: defb 0 org (((last-base)+255) and 0FF00h) -1 defb 0 end ccploc