diff --git a/bdos.asm b/bdos.asm index edc42d6..27e2373 100644 --- a/bdos.asm +++ b/bdos.asm @@ -1,103 +1,77 @@ ; Reformatted and converted for cross-assembly by Macro Assembler AS ; Eric Smith 2018-01-24 -; from original source os3bdos.asm from -; http://www.cpm.z80.de/download/cpm2-plm.zip -; includes Digital Research CP/M V2.2 Patch 01 (cpm22pat.01) from -; http://www.cpm.z80.de/download/cpm22pat.zip - -; Changes: -; multiple instructions per line split to separate lines -; dollar sign in labels replaced by underscore -; dollar sign (as digit separator) in binary constants removed -; no colons for labels for equates -; single quotes around strings replaced with double quotes -; true and false replaced with _true and _false -; eliminated equates for 8080 registers, added comments introduced with % -; replaced "not", "and" operators with "~", "&" -; removed empty comments -; added ifdef origin to allow origin to be specified from command line -; added commments about serial number - - .cpu 8080 - -patch1 equ 1 - - - title "Bdos Interface, Bdos, Version 2.2 Feb, 1980" -;***************************************************************** -;***************************************************************** -;** ** -;** B a s i c D i s k O p e r a t i n g S y s t e m ** -;** I n t e r f a c e M o d u l e ** -;** ** -;***************************************************************** -;***************************************************************** +; ------------------------------------------------------------ +; Clean BDOS Header for fixed-address CP/M system +; ------------------------------------------------------------ +; This version removes Digital Research’s conditional ORG logic. +; BDOS is always located at an explicit address. ; -; Copyright (c) 1978, 1979, 1980 -; Digital Research -; Box 579, Pacific Grove -; California +; Captain’s architecture: +; BDOS @ 0xE000 ; -; -; 20 january 1980 -; -; -on equ 0ffffh -off equ 00000h -test equ off +; Override when building: +; sjasmplus --define=BDOS_ORG=0xE000 bdos.asm +; ------------------------------------------------------------ - ifdef origin - org origin - else - if test - org 0dc00h - else - org 0800h - endif - endif -; bios value defined at end of module +patch1 equ 1 + +; BDOS Interface, BDOS, Version 2.2 + +; ------------------------------------------------------------ +; CP/M fixed memory placement +; ------------------------------------------------------------ + + ifndef BDOS_ORG +BDOS_ORG equ 0E000h ; default BDOS location + endif + + ORG BDOS_ORG + +; BIOS entry point address will be defined later in this module +; (Digital Research placed BIOS just above BDOS; our BIOS is at C000h) -ssize equ 24 ;24 level stack + +ssize equ 24 ;24 level stack ; low memory locations -reboot equ 0000h ;reboot system -ioloc equ 0003h ;i/o byte location -bdosa equ 0006h ;address field of jmp BDOS +reboot equ 0000h ;reboot system +ioloc equ 0003h ;i/o byte location +bdosa equ 0006h ;address field of jmp BDOS ; bios access constants -bootf set bios+3*0 ;cold boot function -wbootf set bios+3*1 ;warm boot function -constf set bios+3*2 ;console status function -coninf set bios+3*3 ;console input function -conoutf set bios+3*4 ;console output function -listf set bios+3*5 ;list output function -punchf set bios+3*6 ;punch output function -readerf set bios+3*7 ;reader input function -homef set bios+3*8 ;disk home function -seldskf set bios+3*9 ;select disk function -settrkf set bios+3*10 ;set track function -setsecf set bios+3*11 ;set sector function -setdmaf set bios+3*12 ;set dma function -readf set bios+3*13 ;read disk function -writef set bios+3*14 ;write disk function -liststf set bios+3*15 ;list status function -sectran set bios+3*16 ;sector translate +bootf equ bios+3*0 ;cold boot function +wbootf equ bios+3*1 ;warm boot function +constf equ bios+3*2 ;console status function +coninf equ bios+3*3 ;console input function +conoutf equ bios+3*4 ;console output function +listf equ bios+3*5 ;list output function +punchf equ bios+3*6 ;punch output function +readerf equ bios+3*7 ;reader input function +homef equ bios+3*8 ;disk home function +seldskf equ bios+3*9 ;select disk function +settrkf equ bios+3*10 ;EQU track function +setsecf equ bios+3*11 ;EQU sector function +setdmaf equ bios+3*12 ;EQU dma function +readf equ bios+3*13 ;read disk function +writef equ bios+3*14 ;write disk function +liststf equ bios+3*15 ;list status function +sectran equ bios+3*16 ;sector translate ; equates for non graphic characters -ctlc equ 03h ;control c -ctle equ 05h ;physical eol -ctlh equ 08h ;backspace -ctlp equ 10h ;prnt toggle -ctlr equ 12h ;repeat line -ctls equ 13h ;stop/start screen -ctlu equ 15h ;line delete -ctlx equ 18h ;=ctl-u -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 +ctlc equ 03h ;control c +ctle equ 05h ;physical eol +ctlh equ 08h ;backspace +ctlp equ 10h ;prnt toggle +ctlr equ 12h ;repeat line +ctls equ 13h ;stop/start screen +ctlu equ 15h ;line delete +ctlx equ 18h ;=ctl-u +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 ; serial number (not documented in original DRI source file) db 0 ; OEM number, low byte @@ -107,7 +81,7 @@ ctl equ 5eh ;up arrow ; enter here from the user's program with function number in c, ; and information address in d,e - jmp bdose ;past parameter block + jp bdose ;past parameter block ; ************************************************ ; *** relative locations 0009 - 000e *** @@ -119,44 +93,44 @@ roferr: dw rofsub ;ro file error subroutine bdose: ;arrive here from user programs - xchg ;info=DE, DE=info - shld info - xchg - mov a,e ;linfo = low(info) - don't equ - sta linfo - lxi h,0 ;return value defaults to 0000 - shld aret - ;save user's stack pointer, set to local stack - dad sp ;entsp = stackptr - shld entsp - lxi sp,lstack ;local stack setup - xra a ;fcbdsk,resel=false - sta fcbdsk - sta resel - lxi h,goback ;return here after all functions - push h ;jmp goback equivalent to ret - mov a,c ;skip if invalid # - cpi nfuncs - rnc - mov c,e ;possible output character to C - lxi h,functab ;DE=func, HL=.ciotab - mov e,a - mvi d,0 - dad d ;DE=functab(func) - dad d - mov e,m - inx h - mov d,m - lhld info ;info in DE for later xchg - xchg ;dispatched - pchl + ex de,hl ;info=DE, DE=info + ld (info),hl + ex de,hl + ld a,e ;linfo = low(info) - don't equ + ld (linfo),a + ld hl,0 ;return value defaults to 0000 + ld (aret),hl + ;save user's stack pointer, EQU to local stack + add hl,sp ;entsp = stackptr + ld (entsp),hl + ld sp,lstack ;local stack setup + xor a ;fcbdsk,resel=false + ld (fcbdsk),a + ld (resel),a + ld hl,goback ;return here after all functions + push hl ;jmp goback equivalent to ret + ld a,c ;skip if invalid # + cp nfuncs + ret nc + ld c,e ;possible output character to C + ld hl,functab ;DE=func, HL=.ciotab + ld e,a + ld d,0 + add hl,de ;DE=functab(func) + add hl,de + ld e,(hl) + inc hl + ld d,(hl) + ld hl,(info) ;info in DE for later xchg + ex de,hl ;dispatched + jp (hl) ; dispatch table for functions functab: dw wbootf, func1, func2, func3 dw punchf, listf, func6, func7 dw func8, func9, func10,func11 -diskf equ ($-functab)/2 ;disk funcs +diskf equ ($-functab)/2 ;disk funcs dw func12,func13,func14,func15 dw func16,func17,func18,func19 dw func20,func21,func22,func23 @@ -170,27 +144,27 @@ nfuncs equ ($-functab)/2 ; error subroutines persub: ;report permanent error - lxi h,permsg ;to report the error + ld hl,permsg ;to report the error call errflg - cpi ctlc ;reboot if response is ctlc - jz reboot - ret ;and ignore the error + cp ctlc ;reboot if response is ctlc + jp z,reboot + ret ;and ignore the error selsub: ;report select error - lxi h,selmsg ;wait console before boot - jmp wait_err + ld hl,selmsg ;wait console before boot + jp wait_err ; rodsub: ;report write to read/only disk - lxi h,rodmsg ;wait console - jmp wait_err + ld hl,rodmsg ;wait console + jp wait_err ; rofsub: ;report read/only file - lxi h,rofmsg ;drop through to wait for console + ld hl,rofmsg ;drop through to wait for console ; wait_err: ;wait for response before boot call errflg - jmp reboot + jp reboot ; error messages dskmsg: db "Bdos Err On " @@ -203,14 +177,14 @@ rodmsg: db "R/O$" errflg: ;report error to console, message address in HL - push h ;stack mssg address, new line + push hl ;stack mssg address, new line call crlf - lda curdsk ;current disk name - adi 'A' - sta dskerr - lxi b,dskmsg ;the error message + ld a,(curdsk) ;current disk name + add a,'A' + ld (dskerr),a + ld bc,dskmsg ;the error message call print - pop b ;error mssage tail + pop bc ;error mssage tail call print ;jmp conin ;to get the input character ;(drop through to conin) @@ -220,373 +194,373 @@ errflg: ; console handlers conin: ;read console character to A - lxi h,kbchar - mov a,m - mvi m,0 - ora a - rnz + ld hl,kbchar + ld a,(hl) + ld (hl),0 + or a + ret nz ;no previous keyboard character ready - jmp coninf ;get character externally + jp coninf ;get character externally ;ret conech: ;read character with echo - call conin ;echo character? + call conin ;echo character? call echoc - rc + ret c ;character must be echoed before return - push psw - mov c,a + push af + ld c,a call tabout - pop psw - ret ;with character in A + pop af + ret ;with character in A echoc: ;echo character if graphic ;cr, lf, tab, or backspace - cpi cr ;carriage return? - rz - cpi lf ;line feed? - rz - cpi tab ;tab? - rz - cpi ctlh ;backspace? - rz - cpi ' ' ;carry set if not graphic - ret + cp cr ;carriage return? + ret z + cp lf ;line feed? + ret z + cp tab ;tab? + ret z + cp ctlh ;backspace? + ret z + cp ' ' ;carry EQU if not graphic + ret conbrk: ;check for character ready - lda kbchar ;skip if active kbchar - ora a - jnz conb1 + ld a,(kbchar) ;skip if active kbchar + or a + jp nz,conb1 ;no active kbchar, check external break - call constf ;return if no char ready - ani 1 - rz + call constf ;return if no char ready + and 1 + ret z ;character ready, read it - call coninf ;to A - cpi ctls ;check stop screen function - jnz conb0 + call coninf ;to A + cp ctls ;check stop screen function + jp nz,conb0 ;found ctls, read next character - call coninf ;to A - cpi ctlc ;ctlc implies re-boot - jz reboot + call coninf ;to A + cp ctlc ;ctlc implies re-boot + jp z,reboot ;not a reboot, act as if nothing has happened - xra a ;with zero in accumulator + xor a ;with zero in accumulator ret conb0: ;character in accum, save it - sta kbchar -conb1: ;return with true set in accumulator - mvi a,1 + ld (kbchar),a +conb1: ;return with true EQU in accumulator + ld a,1 ret conout: ;compute character position/write console char from C ;compcol = true if computing column position - lda compcol - ora a - jnz compout + ld a,(compcol) + or a + jp nz,compout ;write the character, then compute the column ;write console character from C - push b ;check for screen stop function + push bc ;check for screen stop function call conbrk - pop b ;recall/save character - push b - call conoutf ;externally, to console - pop b ;recall/save character - push b + pop bc ;recall/save character + push bc + call conoutf ;externally, to console + pop bc ;recall/save character + push bc ;may be copying to the list device - lda listcp ;to printer, if so - ora a - cnz listf - pop b ;recall the character + ld a,(listcp) ;to printer, if so + or a + call nz,listf + pop bc ;recall the character compout: - mov a,c ;recall the character + ld a,c ;recall the character ;and compute column position - lxi h,column ;A = char, HL = .column - cpi rubout ;no column change if nulls - rz - inr m ;column = column + 1 - cpi ' ' ;return if graphic - rnc - ;not graphic, reset column position - dcr m ;column = column - 1 - mov a,m ;return if at zero - ora a - rz + ld hl,column ;A = char, HL = .column + cp rubout ;no column change if nulls + ret z + inc (hl) ;column = column + 1 + cp ' ' ;return if graphic + ret nc + ;not graphic, reEQU column position + dec (hl) ;column = column - 1 + ld a,(hl) ;return if at zero + or a + ret z ;not at zero, may be backspace or end line - mov a,c ;character back to A - cpi ctlh - jnz notbacksp + ld a,c ;character back to A + cp ctlh + jp nz,notbacksp ;backspace character - dcr m ;column = column - 1 + dec (hl) ;column = column - 1 ret notbacksp: ;not a backspace character, eol? - cpi lf ;return if not - rnz + cp lf ;return if not + ret nz ;end of line, column = 0 - mvi m,0 ;column = 0 + ld (hl),0 ;column = 0 ret ctlout: ;send C character with possible preceding up-arrow - mov a,c ;cy if not graphic (or special case) + ld a,c ;cy if not graphic (or special case) call echoc - jnc tabout ;skip if graphic, tab, cr, lf, or ctlh + jp nc,tabout ;skip if graphic, tab, cr, lf, or ctlh ;send preceding up arrow - push psw ;up arrow - mvi c,ctl + push af ;up arrow + ld c,ctl call conout - pop psw ;becomes graphic letter - ori 40h - mov c,a ;ready to print + pop af ;becomes graphic letter + or 40h + ld c,a ;ready to print ;(drop through to tabout) tabout: ;expand tabs to console - mov a,c ;direct to conout if not - cpi tab - jnz conout + ld a,c ;direct to conout if not + cp tab + jp nz,conout ;tab encountered, move to next tab position tab0: - mvi c,' ' ;another blank + ld c,' ' ;another blank call conout - lda column ;column mod 8 = 0 ? - ani 111b - jnz tab0 ;back for another if not + ld a,(column) ;column mod 8 = 0 ? + and 111b + jp nz,tab0 ;back for another if not ret backup: ;back-up one screen position call pctlh - mvi c,' ' + ld c,' ' call conoutf ; (drop through to pctlh) pctlh: ;send ctlh to console without affecting column count - mvi c,ctlh - jmp conoutf + ld c,ctlh + jp conoutf ;ret crlfp: ;print #, cr, lf for ctlx, ctlu, ctlr functions ;then move to strtcol (starting column) - mvi c,'#' + ld c,'#' call conout call crlf ;column = 0, move to position strtcol crlfp0: - lda column - lxi h,strtcol - cmp m ;stop when column reaches strtcol - rnc - mvi c,' ' ;print blank - call conout - jmp crlfp0 + ld a,(column) + ld hl,strtcol + cp (hl) ;stop when column reaches strtcol + ret nc + ld c,' ' ;print blank + call conout + jp crlfp0 crlf: ;carriage return line feed sequence - mvi c,cr + ld c,cr call conout - mvi c,lf - jmp conout + ld c,lf + jp conout ;ret print: ;print message until M(BC) = '$' - ldax b ;stop on $ - cpi '$' - rz + ld a,(bc) ;stop on $ + cp '$' + ret z ;more to print - inx b ;char to C - push b - mov c,a - call tabout ;another character printed - pop b - jmp print + inc bc ;char to C + push bc + ld c,a + call tabout ;another character printed + pop bc + jp print read: ;read to info address (max length, current length, buffer) - lda column ;save start for ctl-x, ctl-h - sta strtcol - lhld info - mov c,m - inx h - push h - mvi b,0 + ld a,(column) ;save start for ctl-x, ctl-h + ld (strtcol),a + ld hl,(info) + ld c,(hl) + inc hl + push hl + ld b,0 ;B = current buffer length, ;C = maximum buffer length, ;HL= next to fill - 1 readnx: ;read next character, BC, HL active - push b ;blen, cmax, HL saved - push h + push bc ;blen, cmax, HL saved + push hl readn0: - call conin ;next char in A - ani 7fh ;mask parity bit - pop h ;reactivate counters - pop b - cpi cr ;end of line? - jz readen - cpi lf ;also end of line - jz readen - cpi ctlh ;backspace? - jnz noth + call conin ;next char in A + and 7fh ;mask parity bit + pop hl ;reactivate counters + pop bc + cp cr ;end of line? + jp z,readen + cp lf ;also end of line + jp z,readen + cp ctlh ;backspace? + jp nz,noth ;do we have any characters to back over? - mov a,b - ora a - jz readnx + ld a,b + or a + jp z,readnx ;characters remain in buffer, backup one - dcr b ;remove one character - lda column ;col > 0 - sta compcol + dec b ;remove one character + ld a,(column) ;col > 0 + ld (compcol),a ;compcol > 0 marks repeat as length compute - jmp linelen ;uses same code as repeat + jp linelen ;uses same code as repeat noth: ;not a backspace - cpi rubout ;rubout char? - jnz notrub + cp rubout ;rubout char? + jp nz,notrub ;rubout encountered, rubout if possible - mov a,b ;skip if len=0 - ora a - jz readnx + ld a,b ;skip if len=0 + or a + jp z,readnx ;buffer has characters, resend last char - mov a,m ;A = last char - dcr b - dcx h + ld a,(hl) ;A = last char + dec b + dec hl ;blen=blen-1, next to fill - 1 decremented - jmp rdech1 ;act like this is an echo + jp rdech1 ;act like this is an echo notrub: ;not a rubout character, check end line - cpi ctle ;physical end line? - jnz note + cp ctle ;physical end line? + jp nz,note ;yes, save active counters and force eol - push b - push h + push bc + push hl call crlf - xra a ;start position = 00 - sta strtcol - jmp readn0 ;for another character + xor a ;start position = 00 + ld (strtcol),a + jp readn0 ;for another character note: ;not end of line, list toggle? - cpi ctlp ;skip if not ctlp - jnz notp + cp ctlp ;skip if not ctlp + jp nz,notp ;list toggle - change parity - push h ;save next to fill - 1 - lxi h,listcp ;HL=.listcp flag - mvi a,1 ;True-listcp - sub m - mov m,a ;listcp = not listcp - pop h ;for another char - jmp readnx + push hl ;save next to fill - 1 + ld hl,listcp ;HL=.listcp flag + ld a,1 ;True-listcp + sub (hl) + ld (hl),a ;listcp = not listcp + pop hl ;for another char + jp readnx notp: ;not a ctlp, line delete? - cpi ctlx - jnz notx - pop h ;discard start position + cp ctlx + jp nz,notx + pop hl ;discard start position ;loop while column > strtcol backx: - lda strtcol - lxi h,column - cmp m ;start again - jnc read - dcr m ;column = column - 1 - call backup ;one position - jmp backx + ld a,(strtcol) + ld hl,column + cp (hl) ;start again + jp nc,read + dec (hl) ;column = column - 1 + call backup ;one position + jp backx notx: ;not a control x, control u? ;not control-X, control-U? - cpi ctlu ;skip if not - jnz notu + cp ctlu ;skip if not + jp nz,notu ;delete line (ctlu) - call crlfp ;physical eol - pop h ;discard starting position - jmp read ;to start all over + call crlfp ;physical eol + pop hl ;discard starting position + jp read ;to start all over notu: ;not line delete, repeat line? - cpi ctlr - jnz notr + cp ctlr + jp nz,notr linelen: ;repeat line, or compute line len (ctlh) ;if compcol > 0 - push b ;save line length - call crlfp - pop b - pop h - push h - push b + push bc ;save line length + call crlfp + pop bc + pop hl + push hl + push bc ;bcur, cmax active, beginning buff at HL rep0: - mov a,b ;count len to 00 - ora a - jz rep1 - inx h ;next to print - mov c,m - dcr b ;count length down - push b - push h - call ctlout ;character echoed - pop h ;recall remaining count - pop b - jmp rep0 ;for the next character + ld a,b ;count len to 00 + or a + jp z,rep1 + inc hl ;next to print + ld c,(hl) + dec b ;count length down + push bc + push hl + call ctlout ;character echoed + pop hl ;recall remaining count + pop bc + jp rep0 ;for the next character rep1: ;end of repeat, recall lengths ;original BC still remains pushed - push h ;save next to fill - lda compcol ;>0 if computing length - ora a - jz readn0 ;for another char if so + push hl ;save next to fill + ld a,(compcol) ;>0 if computing length + or a + jp z,readn0 ;for another char if so ;column position computed for ctlh - lxi h,column ;diff > 0 - sub m - sta compcol ;count down below + ld hl,column ;diff > 0 + sub (hl) + ld (compcol),a ;count down below ;move back compcol-column spaces backsp: ;move back one more space - call backup ;one space - lxi h,compcol - dcr m - jnz backsp - jmp readn0 ;for next character + call backup ;one space + ld hl,compcol + dec (hl) + jp nz,backsp + jp readn0 ;for next character notr: ;not a ctlr, place into buffer rdecho: - inx h ;character filled to mem - mov m,a - inr b ;blen = blen + 1 + inc hl ;character filled to mem + ld (hl),a + inc b ;blen = blen + 1 rdech1: ;look for a random control character - push b ;active values saved - push h - mov c,a ;ready to print - call ctlout ;may be up-arrow C - pop h ;recall char - pop b - mov a,m - cpi ctlc ;set flags for reboot test - mov a,b ;move length to A - jnz notc ;skip if not a control c - cpi 1 ;control C, must be length 1 - jz reboot ;reboot if blen = 1 + push bc ;active values saved + push hl + ld c,a ;ready to print + call ctlout ;may be up-arrow C + pop hl ;recall char + pop bc + ld a,(hl) + cp ctlc ;EQU flags for reboot test + ld a,b ;move length to A + jp nz,notc ;skip if not a control c + cp 1 ;control C, must be length 1 + jp z,reboot ;reboot if blen = 1 ;length not one, so skip reboot notc: ;not reboot, are we at end of buffer? - cmp c ;go for another if not - jc readnx + cp c ;go for another if not + jp c,readnx readen: ;end of read operation, store blen - pop h ;M(current len) = B - mov m,b - mvi c,cr ;return carriage - jmp conout + pop hl ;M(current len) = B + ld (hl),b + ld c,cr ;return carriage + jp conout ;ret func1: ;return console character with echo call conech - jmp sta_ret + jp sta_ret ; func2 equ tabout ;write console character with tab expansion @@ -594,7 +568,7 @@ func2 equ tabout func3: ;return reader character call readerf - jmp sta_ret + jp sta_ret ;func4: equated to punchf ;write punch character @@ -605,38 +579,38 @@ func3: func6: ;direct console i/o - read if 0ffh - mov a,c ;0ffh => 00h, means input mode - inr a - jz dirinp - inr a ;0feH in C for status - jz constf + ld a,c ;0ffh => 00h, means input mode + inc a + jp z,dirinp + inc a ;0feH in C for status + jp z,constf ;direct output function - jmp conoutf + jp conoutf dirinp: - call constf ;status check - ora a ;skip, return 00 if not ready - jz retmon + call constf ;status check + or a ;skip, return 00 if not ready + jp z,retmon ;character is ready, get it - call coninf ;to A - jmp sta_ret + call coninf ;to A + jp sta_ret func7: ;return io byte - lda ioloc - jmp sta_ret + ld a,(ioloc) + jp sta_ret func8: - ;set i/o byte - lxi h,ioloc - mov m,c - ret ;jmp goback + ;EQU i/o byte + ld hl,ioloc + ld (hl),c + ret ;jmp goback func9: ;write line until $ encountered - xchg ;was lhld info - mov c,l ;BC=string address - mov b,h - jmp print ;out to console + ex de,hl ;was lhld info + ld c,l ;BC=string address + ld b,h + jp print ;out to console func10 equ read ;read a buffered console line @@ -647,14 +621,14 @@ func11: ;(drop through to sta_ret) sta_ret: ;store the A register to aret - sta aret + ld (aret),a func_ret: ; - ret ;jmp goback (pop stack for non cp/m functions) + ret ;jmp goback (pop stack for non cp/m functions) setlret1: - ;set lret = 1 - mvi a,1 - jmp sta_ret + ;EQU lret = 1 + ld a,1 + jp sta_ret @@ -678,7 +652,7 @@ usrcode:db 0 ;current user number curdsk: db 0 ;current disk number info: ds 2 ;information address aret: ds 2 ;address value to return -lret equ aret ;low(aret) +lret equ aret ;low(aret) ;***************************************************************** ;***************************************************************** @@ -688,19 +662,19 @@ lret equ aret ;low(aret) ;***************************************************************** ;***************************************************************** -dvers equ 22h ;version 2.2 +dvers equ 22h ;version 2.2 ; module addresses ; literal constants _true equ 0ffh ;constant true _false equ 000h ;constant false -enddir equ 0ffffh ;end of directory -byte equ 1 ;number of bytes for "byte" type -word equ 2 ;number of bytes for "word" type +enddir equ 0ffffh ;end of directory +byte equ 1 ;number of bytes for "byte" type +word equ 2 ;number of bytes for "word" type ; fixed addresses in low memory -tfcb equ 005ch ;default fcb location -tbuff equ 0080h ;default buffer location +tfcb equ 005ch ;default fcb location +tbuff equ 0080h ;default buffer location ; fixed addresses referenced in bios module are ; pererr (0009), selerr (000c), roderr (000f) @@ -721,16 +695,16 @@ tbuff equ 0080h ;default buffer location sel_error: ;report select error - lxi h,selerr + ld hl,selerr goerr: ;HL = .errorhandler, call subroutine - mov e,m ;address of routine in DE - inx h - mov d,m - xchg ;to subroutine - pchl + ld e,(hl) ;address of routine in DE + inc hl + ld d,(hl) + ex de,hl ;to subroutine + jp (hl) @@ -739,89 +713,89 @@ goerr: move: ;move data length of length C from source DE to ;destination given by HL - inr c ;in case it is zero + inc c ;in case it is zero move0: - dcr c ;more to move - rz - ldax d ;one byte moved - mov m,a - inx d ;to next byte - inx h - jmp move0 + dec c ;more to move + ret z + ld a,(de) ;one byte moved + ld (hl),a + inc de ;to next byte + inc hl + jp move0 selectdisk: ;select the disk drive given by curdsk, and fill ;the base addresses curtrka - alloca, then fill ;the values of the disk parameter block - lda curdsk ;current disk# to c - mov c,a + ld a,(curdsk) ;current disk# to c + ld c,a ;lsb of e = 0 if not yet logged - in - call seldskf ;HL filled by call + call seldskf ;HL filled by call ;HL = 0000 if error, otherwise disk headers - mov a,h ;return with 0000 in HL and z flag - ora l - rz + ld a,h ;return with 0000 in HL and z flag + or l + ret z ;disk header block address in hl - mov e,m ;DE=.tran - inx h - mov d,m - inx h - shld cdrmaxa ;.cdrmax - inx h - inx h - shld curtrka ;HL=.currec - inx h - inx h - shld curreca ;HL=.buffa - inx h - inx h + ld e,(hl) ;DE=.tran + inc hl + ld d,(hl) + inc hl + ld (cdrmaxa),hl ;.cdrmax + inc hl + inc hl + ld (curtrka),hl ;HL=.currec + inc hl + inc hl + ld (curreca),hl ;HL=.buffa + inc hl + inc hl ;DE still contains .tran - xchg ;.tran vector - shld tranv - lxi h,buffa ;DE= source for move, HL=dest - mvi c,addlist ;addlist filled + ex de,hl ;.tran vector + ld (tranv),hl + ld hl,buffa ;DE= source for move, HL=dest + ld c,addlist ;addlist filled call move ;now fill the disk parameter block - lhld dpbaddr ;DE is source - xchg - lxi h,sectpt ;HL is destination - mvi c,dpblist ;data filled + ld hl,(dpbaddr) ;DE is source + ex de,hl + ld hl,sectpt ;HL is destination + ld c,dpblist ;data filled call move - ;now set single/double map mode - lhld maxall ;largest allocation number - mov a,h ;00 indicates < 255 - lxi h,single ;assume a=00 - mvi m,_true - ora a - jz retselect + ;now EQU single/double map mode + ld hl,(maxall) ;largest allocation number + ld a,h ;00 indicates < 255 + ld hl,single ;assume a=00 + ld (hl),_true + or a + jp z,retselect ;high order of maxall not zero, use double dm - mvi m,_false + ld (hl),_false retselect: - mvi a,_true ;select disk function ok - ora a + ld a,_true ;select disk function ok + or a ret home: - ;move to home position, then offset to start of dir - call homef ;move to track 00, sector 00 reference - ;lxi h,offset ;mov c,m ;inx h ;mov b,m ;call settrkf + ;move to home position, then offEQU to start of dir + call homef ;move to track 00, sector 00 reference + ;lxi h,offEQU ;mov c,m ;inx h ;mov b,m ;call settrkf ;first directory position selected - xra a ;constant zero to accumulator - lhld curtrka ;curtrk=0000 - mov m,a - inx h - mov m,a - lhld curreca ;currec=0000 - mov m,a - inx h - mov m,a - ;curtrk, currec both set to 0000 + xor a ;constant zero to accumulator + ld hl,(curtrka) ;curtrk=0000 + ld (hl),a + inc hl + ld (hl),a + ld hl,(curreca) ;currec=0000 + ld (hl),a + inc hl + ld (hl),a + ;curtrk, currec both EQU to 0000 ret rdbuff: ;read buffer and check condition - call readf ;current drive, track, sector, dma - jmp diocomp ;check for i/o errors + call readf ;current drive, track, sector, dma + jp diocomp ;check for i/o errors wrbuff: ;write buffer and check condition @@ -829,20 +803,20 @@ wrbuff: ;wrtype = 0 => normal write operation ;wrtype = 1 => directory write operation ;wrtype = 2 => start of new block - call writef ;current drive, track, sector, dma + call writef ;current drive, track, sector, dma diocomp: ;check for disk errors - ora a - rz - lxi h,pererr - jmp goerr + or a + ret z + ld hl,pererr + jp goerr seek_dir: ;seek the record containing the current dir entry - lhld dcnt ;directory counter to HL - mvi c,dskshf ;value to HL + ld hl,(dcnt) ;directory counter to HL + ld c,dskshf ;value to HL call hlrotr - shld arecord ;ready for seek - shld drec + ld (arecord),hl ;ready for seek + ld (drec),hl ; jmp seek ;ret @@ -859,152 +833,152 @@ seek: ;tcrech equ h ;tcurrec = HL ;tcrecl equ l ;load the registers from memory - lxi h,arecord - mov c,m ; % c = arecl - inx h - mov b,m ; % b = arech - lhld curreca - mov e,m ; % e = crecl - inx h - mov d,m ; % d = crech - lhld curtrka - mov a,m - inx h - mov h,m ; % h = ctrkh - mov l,a ; % l = ctrkl + ld hl,arecord + ld c,(hl) ; % c = arecl + inc hl + ld b,(hl) ; % b = arech + ld hl,(curreca) + ld e,(hl) ; % e = crecl + inc hl + ld d,(hl) ; % d = crech + ld hl,(curtrka) + ld a,(hl) + inc hl + ld h,(hl) ; % h = ctrkh + ld l,a ; % l = ctrkl ;loop while arecord < currec seek0: - mov a,c ; % c = arecl - sub e ; % e = crecl - mov a,b ; % b = arech - sbb d ; % d = crech - jnc seek1 ;skip if arecord >= currec + ld a,c ; % c = arecl + sub e ; % e = crecl + ld a,b ; % b = arech + sbc a,d ; % d = crech + jp nc,seek1 ;skip if arecord >= currec ;currec = currec - sectpt - push h ; % h = ctrkh - lhld sectpt - mov a,e ; % e = crecl + push hl ; % h = ctrkh + ld hl,(sectpt) + ld a,e ; % e = crecl sub l - mov e,a ; % e = crecl - mov a,d ; % d = crech - sbb h - mov d,a ; % d = crech - pop h ; % h = ctrkh + ld e,a ; % e = crecl + ld a,d ; % d = crech + sbc a,h + ld d,a ; % d = crech + pop hl ; % h = ctrkh ;curtrk = curtrk - 1 - dcx h ; % h = ctrkh - jmp seek0 ;for another try + dec hl ; % h = ctrkh + jp seek0 ;for another try seek1: ;look while arecord >= (t:=currec + sectpt) - push h ; % h = ctrkh - lhld sectpt ;HL = currec+sectpt - dad d ; % d = crech - jc seek2 ;can be > FFFFH - mov a,c ; % c = arecl - sub l ; % l = tcrecl - mov a,b ; % b = arech - sbb h ; % h = tcrech - jc seek2 ;skip if t > arecord + push hl ; % h = ctrkh + ld hl,(sectpt) ;HL = currec+sectpt + add hl,de ; % d = crech + jp c,seek2 ;can be > FFFFH + ld a,c ; % c = arecl + sub l ; % l = tcrecl + ld a,b ; % b = arech + sbc a,h ; % h = tcrech + jp c,seek2 ;skip if t > arecord ;currec = t - xchg + ex de,hl ;curtrk = curtrk + 1 - pop h ; % h = ctrkh - inx h ; % h = ctrkh - jmp seek1 ;for another try -seek2: pop h ; % h = ctrkh + pop hl ; % h = ctrkh + inc hl ; % h = ctrkh + jp seek1 ;for another try +seek2: pop hl ; % h = ctrkh ;arrive here with updated values in each register - push b ;to stack for later ; % b = arech - push d ; % d = crech - push h ; % h = ctrkh + push bc ;to stack for later ; % b = arech + push de ; % d = crech + push hl ; % h = ctrkh ;stack contains (lowest) BC=arecord, DE=currec, HL=curtrk - xchg ;HL = curtrk+offset - lhld offset - dad d - mov b,h ;track set up - mov c,l + ex de,hl ;HL = curtrk+offset + ld hl,(offset) + add hl,de + ld b,h ;track EQU up + ld c,l call settrkf ;note that BC - curtrk is difference to move in bios - pop d ;recall curtrk - lhld curtrka ;curtrk updated - mov m,e - inx h - mov m,d + pop de ;recall curtrk + ld hl,(curtrka) ;curtrk updated + ld (hl),e + inc hl + ld (hl),d ;now compute sector as arecord-currec - pop d ;recall currec ; % d = crech - lhld curreca - mov m,e ; % e = crecl - inx h - mov m,d ; % d = crech - pop b ;BC=arecord, DE=currec ; % b = arech - mov a,c ; % c = arecl - sub e ; % e = crecl - mov c,a ; % c = arecl - mov a,b ; % b = arech - sbb d ; % d = crech - mov b,a ; % b = arech - lhld tranv ;BC=sector#, DE=.tran - xchg - call sectran ;HL = tran(sector) - mov c,l ;BC = tran(sector) - mov b,h - jmp setsecf ;sector selected + pop de ;recall currec ; % d = crech + ld hl,(curreca) + ld (hl),e ; % e = crecl + inc hl + ld (hl),d ; % d = crech + pop bc ;BC=arecord, DE=currec ; % b = arech + ld a,c ; % c = arecl + sub e ; % e = crecl + ld c,a ; % c = arecl + ld a,b ; % b = arech + sbc a,d ; % d = crech + ld b,a ; % b = arech + ld hl,(tranv) ;BC=sector#, DE=.tran + ex de,hl + call sectran ;HL = tran(sector) + ld c,l ;BC = tran(sector) + ld b,h + jp setsecf ;sector selected ;ret ; file control block (fcb) constants -empty equ 0e5h ;empty directory entry -lstrec equ 127 ;last record# in extent -recsiz equ 128 ;record size -fcblen equ 32 ;file control block size -dirrec equ recsiz/fcblen ;directory elts / record -dskshf equ 2 ;log2(dirrec) +empty equ 0e5h ;empty directory entry +lstrec equ 127 ;last record# in extent +recsiz equ 128 ;record size +fcblen equ 32 ;file control block size +dirrec equ recsiz/fcblen ;directory elts / record +dskshf equ 2 ;log2(dirrec) dskmsk equ dirrec-1 -fcbshf equ 5 ;log2(fcblen) - -extnum equ 12 ;extent number field -maxext equ 31 ;largest extent number -ubytes equ 13 ;unfilled bytes field -modnum equ 14 ;data module number -maxmod equ 15 ;largest module number -fwfmsk equ 80h ;file write flag is high order modnum -namlen equ 15 ;name length -reccnt equ 15 ;record count field -dskmap equ 16 ;disk map field +fcbshf equ 5 ;log2(fcblen) + +extnum equ 12 ;extent number field +maxext equ 31 ;largest extent number +ubytes equ 13 ;unfilled bytes field +modnum equ 14 ;data module number +maxmod equ 15 ;largest module number +fwfmsk equ 80h ;file write flag is high order modnum +namlen equ 15 ;name length +reccnt equ 15 ;record count field +dskmap equ 16 ;disk map field lstfcb equ fcblen-1 nxtrec equ fcblen -ranrec equ nxtrec+1;random record field (2 bytes) +ranrec equ nxtrec+1 ;random record field (2 bytes) ; reserved file indicators -rofile equ 9 ;high order of first type char -invis equ 10 ;invisible file in dir command +rofile equ 9 ;high order of first type char +invis equ 10 ;invisible file in dir command ; equ 11 ;reserved ; utility functions for file access dm_position: ;compute disk map position for vrecord to HL - lxi h,blkshf ;shift count to C - mov c,m - lda vrecord ;current virtual record to A + ld hl,blkshf ;shift count to C + ld c,(hl) + ld a,(vrecord) ;current virtual record to A dmpos0: - ora a - rar - dcr c - jnz dmpos0 + or a + rr a + dec c + jp nz,dmpos0 ;A = shr(vrecord,blkshf) = vrecord/2**(sect/block) - mov b,a ;save it for later addition - mvi a,8 ;8-blkshf to accumulator - sub m - mov c,a ;extent shift count in register c - lda extval ;extent value ani extmsk + ld b,a ;save it for later addition + ld a,8 ;8-blkshf to accumulator + sub (hl) + ld c,a ;extent shift count in register c + ld a,(extval) ;extent value ani extmsk dmpos1: ;blkshf = 3,4,5,6,7, C=5,4,3,2,1 ;shift is 4,3,2,1,0 - dcr c - jz dmpos2 - ora a - ral - jmp dmpos1 + dec c + jp z,dmpos2 + or a + rl a + jp dmpos1 dmpos2: ;arrive here with A = shl(ext and extmsk,7-blkshf) - add b ;add the previous shr(vrecord,blkshf) value + add a,b ;add the previous shr(vrecord,blkshf) value ;A is one of the following values, depending upon alloc ;bks blkshf ;1k 3 v/8 + extval * 16 @@ -1012,228 +986,228 @@ dmpos2: ;4k 5 v/32+ extval * 4 ;8k 6 v/64+ extval * 2 ;16k 7 v/128+extval * 1 - ret ;with dm_position in A + ret ;with dm_position in A getdm: ;return disk map value from position given by BC - lhld info ;base address of file control block - lxi d,dskmap ;HL =.diskmap - dad d - dad b ;index by a single byte value - lda single ;single byte/map entry? - ora a ;get disk map single byte - jz getdmd - mov l,m ;with HL=00bb - mvi h,0 + ld hl,(info) ;base address of file control block + ld de,dskmap ;HL =.diskmap + add hl,de + add hl,bc ;index by a single byte value + ld a,(single) ;single byte/map entry? + or a ;get disk map single byte + jp z,getdmd + ld l,(hl) ;with HL=00bb + ld h,0 ret getdmd: - dad b ;HL=.fcb(dm+i*2) + add hl,bc ;HL=.fcb(dm+i*2) ;double precision value returned - mov e,m - inx h - mov d,m - xchg + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl ret index: ;compute disk block number from current fcb - call dm_position ;0...15 in register A - mov c,a ;value to HL - mvi b,0 + call dm_position ;0...15 in register A + ld c,a ;value to HL + ld b,0 call getdm - shld arecord + ld (arecord),hl ret allocated: ;called following index to see if block allocated - lhld arecord - mov a,l - ora h + ld hl,(arecord) + ld a,l + or h ret atran: ;compute actual record address, assuming index called - lda blkshf ;shift count to reg A - lhld arecord + ld a,(blkshf) ;shift count to reg A + ld hl,(arecord) atran0: - dad h ;shl(arecord,blkshf) - dcr a - jnz atran0 - shld arecord1 ;save shifted block # - lda blkmsk ;mask value to C - mov c,a - lda vrecord ;masked value in A - ana c - ora l ;to HL - mov l,a - shld arecord ;arecord=HL or (vrecord and blkmsk) + add hl,hl ;shl(arecord,blkshf) + dec a + jp nz,atran0 + ld (arecord1),hl ;save shifted block # + ld a,(blkmsk) ;mask value to C + ld c,a + ld a,(vrecord) ;masked value in A + and c + or l ;to HL + ld l,a + ld (arecord),hl ;arecord=HL or (vrecord and blkmsk) ret getexta: ;get current extent field address to A - lhld info ;HL=.fcb(extnum) - lxi d,extnum - dad d + ld hl,(info) ;HL=.fcb(extnum) + ld de,extnum + add hl,de ret getfcba: ;compute reccnt and nxtrec addresses for get/setfcb - lhld info ;DE=.fcb(reccnt) - lxi d,reccnt - dad d - xchg - lxi h,(nxtrec-reccnt) ;HL=.fcb(nxtrec) - dad d + ld hl,(info) ;DE=.fcb(reccnt) + ld de,reccnt + add hl,de + ex de,hl + ld hl,(nxtrec-reccnt) ;HL=.fcb(nxtrec) + add hl,de ret getfcb: - ;set variables from currently addressed fcb - call getfcba ;addresses in DE, HL - mov a,m ;vrecord=fcb(nxtrec) - sta vrecord - xchg ;rcount=fcb(reccnt) - mov a,m - sta rcount - call getexta ;HL=.fcb(extnum) - lda extmsk ;extent mask to a - ana m ;fcb(extnum) and extmsk - sta extval + ;EQU variables from currently addressed fcb + call getfcba ;addresses in DE, HL + ld a,(hl) ;vrecord=fcb(nxtrec) + ld (vrecord),a + ex de,hl ;rcount=fcb(reccnt) + ld a,(hl) + ld (rcount),a + call getexta ;HL=.fcb(extnum) + ld a,(extmsk) ;extent mask to a + and (hl) ;fcb(extnum) and extmsk + ld (extval),a ret setfcb: ;place values back into current fcb - call getfcba ;addresses to DE, HL - lda seqio - cpi 02 ;check ranfill - jnz setfcb1 - xra a + call getfcba ;addresses to DE, HL + ld a,(seqio) + cp 02 ;check ranfill + jp nz,setfcb1 + xor a setfcb1: - mov c,a ;=1 if sequential i/o - lda vrecord ;fcb(nxtrec)=vrecord+seqio - add c - mov m,a - xchg ;fcb(reccnt)=rcount - lda rcount - mov m,a + ld c,a ;=1 if sequential i/o + ld a,(vrecord) ;fcb(nxtrec)=vrecord+seqio + add a,c + ld (hl),a + ex de,hl ;fcb(reccnt)=rcount + ld a,(rcount) + ld (hl),a ret hlrotr: ;hl rotate right by amount C - inr c ;in case zero + inc c ;in case zero hlrotr0: - dcr c ;return when zero - rz - mov a,h ;high byte - ora a - rar - mov h,a - mov a,l ;low byte - rar - mov l,a - jmp hlrotr0 + dec c ;return when zero + ret z + ld a,h ;high byte + or a + rr a + ld h,a + ld a,l ;low byte + rr a + ld l,a + jp hlrotr0 compute_cs: ;compute checksum for current directory buffer - mvi c,recsiz ;size of directory buffer - lhld buffa ;current directory buffer - xra a ;clear checksum value + ld c,recsiz ;size of directory buffer + ld hl,(buffa) ;current directory buffer + xor a ;clear checksum value computecs0: - add m ;cs=cs+buff(recsiz-C) - inx h - dcr c - jnz computecs0 - ret ;with checksum in A + add a,(hl) ;cs=cs+buff(recsiz-C) + inc hl + dec c + jp nz,computecs0 + ret ;with checksum in A hlrotl: ;rotate the mask in HL by amount in C - inr c ;may be zero + inc c ;may be zero hlrotl0: - dcr c ;return if zero - rz - dad h - jmp hlrotl0 + dec c ;return if zero + ret z + add hl,hl + jp hlrotl0 set_cdisk: - ;set a "1" value in curdsk position of BC - push b ;save input parameter - lda curdsk ;ready parameter for shift - mov c,a - lxi h,1 ;number to shift - call hlrotl ;HL = mask to integrate - pop b ;original mask - mov a,c - ora l - mov l,a - mov a,b ;HL = mask or rol(1,curdsk) - ora h - mov h,a + ;EQU a "1" value in curdsk position of BC + push bc ;save input parameter + ld a,(curdsk) ;ready parameter for shift + ld c,a + ld hl,1 ;number to shift + call hlrotl ;HL = mask to integrate + pop bc ;original mask + ld a,c + or l + ld l,a + ld a,b ;HL = mask or rol(1,curdsk) + or h + ld h,a ret nowrite: ;return true if dir checksum difference occurred - lhld rodsk - lda curdsk - mov c,a + ld hl,(rodsk) + ld a,(curdsk) + ld c,a call hlrotr - mov a,l ;non zero if nowrite - ani 1b + ld a,l ;non zero if nowrite + and 1b ret set_ro: - ;set current disk to read only - lxi h,rodsk - mov c,m - inx h - mov b,m - call set_cdisk ;sets bit to 1 - shld rodsk + ;EQU current disk to read only + ld hl,rodsk + ld c,(hl) + inc hl + ld b,(hl) + call set_cdisk ;sets bit to 1 + ld (rodsk),hl ;high water mark in directory goes to max - lhld dirmax ;DE = directory max - inx h - xchg - lhld cdrmaxa ;HL = .cdrmax - mov m,e ;cdrmax = dirmax - inx h - mov m,d + ld hl,(dirmax) ;DE = directory max + inc hl + ex de,hl + ld hl,(cdrmaxa) ;HL = .cdrmax + ld (hl),e ;cdrmax = dirmax + inc hl + ld (hl),d ret check_rodir: ;check current directory element for read/only status - call getdptra ;address of element + call getdptra ;address of element check_rofile: ;check current buff(dptr) or fcb(0) for r/o status - lxi d,rofile ;offset to ro bit - dad d - mov a,m ;return if not set - ral - rnc - lxi h,roferr - jmp goerr + ld de,rofile ;offEQU to ro bit + add hl,de + ld a,(hl) ;return if not set + rl a + ret nc + ld hl,roferr + jp goerr ; jmp rof_error ;exit to read only disk message check_write: ;check for write protected disk - call nowrite ;ok to write if not rodsk - rz - lxi h,roderr - jmp goerr + call nowrite ;ok to write if not rodsk + ret z + ld hl,roderr + jp goerr ; jmp rod_error ;read only disk error getdptra: ;compute the address of a directory element at ;positon dptr in the buffer - lhld buffa - lda dptr + ld hl,(buffa) + ld a,(dptr) addh: ;HL = HL + A - add l - mov l,a - rnc + add a,l + ld l,a + ret nc ;overflow to H - inr h + inc h ret @@ -1241,190 +1215,190 @@ getmodnum: ;compute the address of the module number ;bring module number to accumulator ;(high order bit is fwf (file write flag) - lhld info ;HL=.fcb(modnum) - lxi d,modnum - dad d - mov a,m ;A=fcb(modnum) + ld hl,(info) ;HL=.fcb(modnum) + ld de,modnum + add hl,de + ld a,(hl) ;A=fcb(modnum) ret clrmodnum: ;clear the module number field for user open/make - call getmodnum ;fcb(modnum)=0 - mvi m,0 + call getmodnum ;fcb(modnum)=0 + ld (hl),0 ret setfwf: - call getmodnum ;HL=.fcb(modnum), A=fcb(modnum) - ;set fwf (file write flag) to "1" - ori fwfmsk ;fcb(modnum)=fcb(modnum) or 80h - mov m,a + call getmodnum ;HL=.fcb(modnum), A=fcb(modnum) + ;EQU fwf (file write flag) to "1" + or fwfmsk ;fcb(modnum)=fcb(modnum) or 80h + ld (hl),a ;also returns non zero in accumulator ret compcdr: ;return cy if cdrmax > dcnt - lhld dcnt ;DE = directory counter - xchg - lhld cdrmaxa ;HL=.cdrmax - mov a,e ;low(dcnt) - low(cdrmax) - sub m - inx h ;HL = .cdrmax+1 - mov a,d ;hig(dcnt) - hig(cdrmax) - sbb m + ld hl,(dcnt) ;DE = directory counter + ex de,hl + ld hl,(cdrmaxa) ;HL=.cdrmax + ld a,e ;low(dcnt) - low(cdrmax) + sub (hl) + inc hl ;HL = .cdrmax+1 + ld a,d ;hig(dcnt) - hig(cdrmax) + sbc a,(hl) ;condition dcnt - cdrmax produces cy if cdrmax>dcnt ret setcdr: ;if not (cdrmax > dcnt) then cdrmax = dcnt+1 call compcdr - rc ;return if cdrmax > dcnt + ret c ;return if cdrmax > dcnt ;otherwise, HL = .cdrmax+1, DE = dcnt - inx d - mov m,d - dcx h - mov m,e + inc de + ld (hl),d + dec hl + ld (hl),e ret subdh: ;compute HL = DE - HL - mov a,e + ld a,e sub l - mov l,a - mov a,d - sbb h - mov h,a + ld l,a + ld a,d + sbc a,h + ld h,a ret newchecksum: - mvi c,_true ;drop through to compute new checksum + ld c,_true ;drop through to compute new checksum checksum: ;compute current checksum record and update the ;directory element if C=true, or check for = if not ;drec < chksiz? - lhld drec ;DE-HL - xchg - lhld chksiz + ld hl,(drec) ;DE-HL + ex de,hl + ld hl,(chksiz) call subdh - rnc ;skip checksum if past checksum vector size + ret nc ;skip checksum if past checksum vector size ;drec < chksiz, so continue - push b ;save init flag - call compute_cs ;check sum value to A - lhld checka ;address of check sum vector - xchg - lhld drec ;value of drec - dad d ;HL = .check(drec) - pop b ;recall true=0ffh or false=00 to C - inr c ;0ffh produces zero flag - jz initial_cs + push bc ;save init flag + call compute_cs ;check sum value to A + ld hl,(checka) ;address of check sum vector + ex de,hl + ld hl,(drec) ;value of drec + add hl,de ;HL = .check(drec) + pop bc ;recall true=0ffh or false=00 to C + inc c ;0ffh produces zero flag + jp z,initial_cs ;not initializing, compare - cmp m ;compute_cs=check(drec)? - rz ;no message if ok + cp (hl) ;compute_cs=check(drec)? + ret z ;no message if ok ;checksum error, are we beyond ;the end of the disk? call compcdr - rnc ;no message if so - call set_ro ;read/only disk set + ret nc ;no message if so + call set_ro ;read/only disk set ret initial_cs: ;initializing the checksum - mov m,a + ld (hl),a ret wrdir: - ;write the current directory entry, set checksum - call newchecksum ;initialize entry - call setdir ;directory dma - mvi c,1 ;indicates a write directory operation - call wrbuff ;write the buffer - jmp setdata ;to data dma address + ;write the current directory entry, EQU checksum + call newchecksum ;initialize entry + call setdir ;directory dma + ld c,1 ;indicates a write directory operation + call wrbuff ;write the buffer + jp setdata ;to data dma address ;ret rd_dir: ;read a directory entry into the directory buffer - call setdir ;directory dma - call rdbuff ;directory record loaded + call setdir ;directory dma + call rdbuff ;directory record loaded ; jmp setdata to data dma address ;ret setdata: - ;set data dma address - lxi h,dmaad ;to complete the call - jmp setdma + ;EQU data dma address + ld hl,dmaad ;to complete the call + jp setdma setdir: - ;set directory dma address - lxi h,buffa ;jmp setdma to complete call + ;EQU directory dma address + ld hl,buffa ;jmp setdma to complete call setdma: - ;HL=.dma address to set (i.e., buffa or dmaad) - mov c,m ;parameter ready - inx h - mov b,m - jmp setdmaf + ;HL=.dma address to EQU (i.e., buffa or dmaad) + ld c,(hl) ;parameter ready + inc hl + ld b,(hl) + jp setdmaf dir_to_user: ;copy the directory entry to the user buffer ;after call to search or searchn by user code - lhld buffa ;source is directory buffer - xchg - lhld dmaad ;destination is user dma address - mvi c,recsiz ;copy entire record - jmp move + ld hl,(buffa) ;source is directory buffer + ex de,hl + ld hl,(dmaad) ;destination is user dma address + ld c,recsiz ;copy entire record + jp move ;ret end_of_dir: ;return zero flag if at end of directory, non zero ;if not at end (end of dir if dcnt = 0ffffh) - lxi h,dcnt ;may be 0ffh - mov a,m - inx h ;low(dcnt) = high(dcnt)? - cmp m - rnz ;non zero returned if different + ld hl,dcnt ;may be 0ffh + ld a,(hl) + inc hl ;low(dcnt) = high(dcnt)? + cp (hl) + ret nz ;non zero returned if different ;high and low the same, = 0ffh? - inr a ;0ffh becomes 00 if so + inc a ;0ffh becomes 00 if so ret set_end_dir: - ;set dcnt to the end of the directory - lxi h,enddir - shld dcnt + ;EQU dcnt to the end of the directory + ld hl,enddir + ld (dcnt),hl ret read_dir: ;read next directory entry, with C=true if initializing - lhld dirmax ;in preparation for subtract - xchg - lhld dcnt ;dcnt=dcnt+1 - inx h - shld dcnt + ld hl,(dirmax) ;in preparation for subtract + ex de,hl + ld hl,(dcnt) ;dcnt=dcnt+1 + inc hl + ld (dcnt),hl ;continue while dirmax >= dcnt (dirmax-dcnt no cy) - call subdh ;DE-HL - jnc read_dir0 - ;yes, set dcnt to end of directory - jmp set_end_dir + call subdh ;DE-HL + jp nc,read_dir0 + ;yes, EQU dcnt to end of directory + jp set_end_dir ; ret read_dir0: ;not at end of directory, seek next element ;initialization flag is in C - lda dcnt ;low(dcnt) and dskmsk - ani dskmsk - mvi b,fcbshf ;to multiply by fcb size + ld a,(dcnt) ;low(dcnt) and dskmsk + and dskmsk + ld b,fcbshf ;to multiply by fcb size read_dir1: - add a - dcr b - jnz read_dir1 + add a,a + dec b + jp nz,read_dir1 ;A = (low(dcnt) and dskmsk) shl fcbshf - sta dptr ;ready for next dir operation - ora a ;return if not a new record - rnz - push b ;save initialization flag C - call seek_dir ;seek proper record - call rd_dir ;read the directory record - pop b ;recall initialization flag - jmp checksum ;checksum the directory elt + ld (dptr),a ;ready for next dir operation + or a ;return if not a new record + ret nz + push bc ;save initialization flag C + call seek_dir ;seek proper record + call rd_dir ;read the directory record + pop bc ;recall initialization flag + jp checksum ;checksum the directory elt ;ret @@ -1435,395 +1409,395 @@ getallocbit: ;the address of the byte for possible replacement in ;memory upon return, and D contains the number of shifts ;required to place the returned value back into position - mov a,c - ani 111b - inr a - mov e,a - mov d,a + ld a,c + and 111b + inc a + ld e,a + ld d,a ;d and e both contain the number of bit positions to shift - mov a,c ;C shr 3 to C - rrc - rrc - rrc - ani 11111b - mov c,a - mov a,b ;B shl 5 - add a - add a - add a - add a - add a - ora c ;bbbccccc to C - mov c,a - mov a,b ;BC shr 3 to BC - rrc - rrc - rrc - ani 11111b - mov b,a - lhld alloca ;base address of allocation vector - dad b ;byte to A, hl = .alloc(BC shr 3) - mov a,m + ld a,c ;C shr 3 to C + rrca + rrca + rrca + and 11111b + ld c,a + ld a,b ;B shl 5 + add a,a + add a,a + add a,a + add a,a + add a,a + or c ;bbbccccc to C + ld c,a + ld a,b ;BC shr 3 to BC + rrca + rrca + rrca + and 11111b + ld b,a + ld hl,(alloca) ;base address of allocation vector + add hl,bc ;byte to A, hl = .alloc(BC shr 3) + ld a,(hl) ;now move the bit to the low order position of A -rotl: rlc - dcr e - jnz rotl +rotl: rlca + dec e + jp nz,rotl ret set_alloc_bit: - ;BC is the bit position of ALLOC to set or reset. The + ;BC is the bit position of ALLOC to EQU or reset. The ;value of the bit is in register E. - push d ;shifted val A, count in D + push de ;shifted val A, count in D call getallocbit - ani 11111110b ;mask low bit to zero (may be set) - pop b ;low bit of C is masked into A - ora c + and 11111110b ;mask low bit to zero (may be set) + pop bc ;low bit of C is masked into A + or c ; jmp rotr ;to rotate back into proper position ;ret rotr: ;byte value from ALLOC is in register A, with shift count ;in register C (to place bit back into position), and ;target ALLOC position in registers HL, rotate and replace - rrc ;back into position - dcr d - jnz rotr - mov m,a ;back to ALLOC + rrca ;back into position + dec d + jp nz,rotr + ld (hl),a ;back to ALLOC ret scandm: ;scan the disk map addressed by dptr for non-zero ;entries, the allocation vector entry corresponding - ;to a non-zero entry is set to the value of C (0,1) - call getdptra ;HL = buffa + dptr + ;to a non-zero entry is EQU to the value of C (0,1) + call getdptra ;HL = buffa + dptr ;HL addresses the beginning of the directory entry - lxi d,dskmap ;hl now addresses the disk map - dad d - push b ;save the 0/1 bit to set - mvi c,fcblen-dskmap+1 ;size of single byte disk map + 1 + ld de,dskmap ;hl now addresses the disk map + add hl,de + push bc ;save the 0/1 bit to set + ld c,fcblen-dskmap+1 ;size of single byte disk map + 1 scandm0: ;loop once for each disk map entry - pop d ;recall bit parity - dcr c ;all done scanning? - rz + pop de ;recall bit parity + dec c ;all done scanning? + ret z ;no, get next entry for scan - push d ;replace bit parity - lda single - ora a - jz scandm1 + push de ;replace bit parity + ld a,(single) + or a + jp z,scandm1 ;single byte scan operation - push b ;save counter - push h ;save map address - mov c,m ;BC=block# - mvi b,0 - jmp scandm2 + push bc ;save counter + push hl ;save map address + ld c,(hl) ;BC=block# + ld b,0 + jp scandm2 scandm1: ;double byte scan operation - dcr c ;count for double byte - push b ;save counter - mov c,m ;BC=block# - inx h - mov b,m - push h ;save map address + dec c ;count for double byte + push bc ;save counter + ld c,(hl) ;BC=block# + inc hl + ld b,(hl) + push hl ;save map address scandm2: ;arrive here with BC=block#, E=0/1 - mov a,c ;skip if = 0000 - ora b - jz scanm3 - lhld maxall ;check invalid index - mov a,l ;maxall - block# + ld a,c ;skip if = 0000 + or b + jp z,scanm3 + ld hl,(maxall) ;check invalid index + ld a,l ;maxall - block# sub c - mov a,h - sbb b - cnc set_alloc_bit - ;bit set to 0/1 + ld a,h + sbc a,b + call nc,set_alloc_bit + ;bit EQU to 0/1 scanm3: - pop h ;to next bit position - inx h - pop b ;recall counter - jmp scandm0 ;for another item + pop hl ;to next bit position + inc hl + pop bc ;recall counter + jp scandm0 ;for another item initialize: ;initialize the current disk - ;lret = false ;set to true if $ file exists + ;lret = false ;EQU to true if $ file exists ;compute the length of the allocation vector - 2 - lhld maxall ;perform maxall/8 - mvi c,3 + ld hl,(maxall) ;perform maxall/8 + ld c,3 ;number of bytes in alloc vector is (maxall/8)+1 - call hlrotr ;HL = maxall/8+1 - inx h - mov b,h ;count down BC til zero - mov c,l - lhld alloca ;base of allocation vector + call hlrotr ;HL = maxall/8+1 + inc hl + ld b,h ;count down BC til zero + ld c,l + ld hl,(alloca) ;base of allocation vector ;fill the allocation vector with zeros initial0: - mvi m,0 ;alloc(i)=0 - inx h - dcx b ;count length down - mov a,b - ora c - jnz initial0 - ;set the reserved space for the directory - lhld dirblk - xchg - lhld alloca ;HL=.alloc() - mov m,e ;sets reserved directory blks - inx h - mov m,d + ld (hl),0 ;alloc(i)=0 + inc hl + dec bc ;count length down + ld a,b + or c + jp nz,initial0 + ;EQU the reserved space for the directory + ld hl,(dirblk) + ex de,hl + ld hl,(alloca) ;HL=.alloc() + ld (hl),e ;sets reserved directory blks + inc hl + ld (hl),d ;allocation vector initialized, home disk call home ;cdrmax = 3 (scans at least one directory record) - lhld cdrmaxa - mvi m,3 - inx h - mvi m,0 + ld hl,(cdrmaxa) + ld (hl),3 + inc hl + ld (hl),0 ;cdrmax = 0000 - call set_end_dir ;dcnt = enddir + call set_end_dir ;dcnt = enddir ;read directory entries and check for allocated storage initial2: - mvi c,_true + ld c,_true call read_dir - call end_of_dir ;return if end of directory - rz + call end_of_dir ;return if end of directory + ret z ;not end of directory, valid entry? - call getdptra ;HL = buffa + dptr - mvi a,empty - cmp m - jz initial2 ;go get another item + call getdptra ;HL = buffa + dptr + ld a,empty + cp (hl) + jp z,initial2 ;go get another item ;not empty, user code the same? - lda usrcode - cmp m - jnz pdollar + ld a,(usrcode) + cp (hl) + jp nz,pdollar ;same user code, check for '$' submit - inx h ;first character - mov a,m - sui '$' ;dollar file? - jnz pdollar + inc hl ;first character + ld a,(hl) + sub '$' ;dollar file? + jp nz,pdollar ;dollar file found, mark in lret - dcr a ;lret = 255 - sta lret + dec a ;lret = 255 + ld (lret),a pdollar: ;now scan the disk map for allocated blocks - mvi c,1 ;set to allocated + ld c,1 ;EQU to allocated call scandm - call setcdr ;set cdrmax to dcnt - jmp initial2 ;for another entry + call setcdr ;EQU cdrmax to dcnt + jp initial2 ;for another entry copy_dirloc: ;copy directory location to lret following ;delete, rename, ... ops - lda dirloc - jmp sta_ret + ld a,(dirloc) + jp sta_ret ; ret compext: ;compare extent# in A with that in C, return nonzero ;if they do not match - push b ;save C's original value - push psw - lda extmsk - cma - mov b,a + push bc ;save C's original value + push af + ld a,(extmsk) + cpl + ld b,a ;B has negated form of extent mask - mov a,c ;low bits removed from C - ana b - mov c,a - pop psw ;low bits removed from A - ana b - sub c ;set flags - ani maxext - pop b ;restore original values + ld a,c ;low bits removed from C + and b + ld c,a + pop af ;low bits removed from A + and b + sub c ;EQU flags + and maxext + pop bc ;restore original values ret search: ;search for directory element of length C at info - mvi a,0ffh ;changed if actually found - sta dirloc - lxi h,searchl ;searchl = C - mov m,c - lhld info ;searcha = info - shld searcha - call set_end_dir ;dcnt = enddir - call home ;to start at the beginning + ld a,0ffh ;changed if actually found + ld (dirloc),a + ld hl,searchl ;searchl = C + ld (hl),c + ld hl,(info) ;searcha = info + ld (searcha),hl + call set_end_dir ;dcnt = enddir + call home ;to start at the beginning ;(drop through to searchn) searchn: ;search for the next directory element, assuming ;a previous call on search which sets searcha and ;searchl - mvi c,_false ;read next dir element + ld c,_false ;read next dir element call read_dir - call end_of_dir ;skip to end if so - jz search_fin + call end_of_dir ;skip to end if so + jp z,search_fin ;not end of directory, scan for match - lhld searcha ;DE=beginning of user fcb - xchg - ldax d ;first character - cpi empty ;keep scanning if empty - jz searchnext + ld hl,(searcha) ;DE=beginning of user fcb + ex de,hl + ld a,(de) ;first character + cp empty ;keep scanning if empty + jp z,searchnext ;not empty, may be end of logical directory - push d ;save search address - call compcdr ;past logical end? - pop d ;recall address - jnc search_fin ;artificial stop + push de ;save search address + call compcdr ;past logical end? + pop de ;recall address + jp nc,search_fin ;artificial stop searchnext: - call getdptra ;HL = buffa+dptr - lda searchl ;length of search to c - mov c,a - mvi b,0 ;b counts up, c counts down + call getdptra ;HL = buffa+dptr + ld a,(searchl) ;length of search to c + ld c,a + ld b,0 ;b counts up, c counts down searchloop: - mov a,c - ora a - jz endsearch - ldax d ;? matches all - cpi '?' - jz searchok + ld a,c + or a + jp z,endsearch + ld a,(de) ;? matches all + cp '?' + jp z,searchok ;scan next character if not ubytes - mov a,b - cpi ubytes - jz searchok + ld a,b + cp ubytes + jp z,searchok ;not the ubytes field, extent field? - cpi extnum ;may be extent field - ldax d ;fcb character - jz searchext ;skip to search extent - sub m ;mask-out flags/extent modulus - ani 7fh - jnz searchn ;skip if not matched - jmp searchok ;matched character + cp extnum ;may be extent field + ld a,(de) ;fcb character + jp z,searchext ;skip to search extent + sub (hl) ;mask-out flags/extent modulus + and 7fh + jp nz,searchn ;skip if not matched + jp searchok ;matched character searchext: ;A has fcb character ;attempt an extent # match - push b ;save counters - mov c,m ;directory character to c - call compext ;compare user/dir char - pop b ;recall counters - jnz searchn ;skip if no match + push bc ;save counters + ld c,(hl) ;directory character to c + call compext ;compare user/dir char + pop bc ;recall counters + jp nz,searchn ;skip if no match searchok: ;current character matches - inx d - inx h - inr b - dcr c - jmp searchloop + inc de + inc hl + inc b + dec c + jp searchloop endsearch: ;entire name matches, return dir position - lda dcnt - ani dskmsk - sta lret + ld a,(dcnt) + and dskmsk + ld (lret),a ;lret = low(dcnt) and 11b - lxi h,dirloc ;dirloc=0ffh? - mov a,m - ral - rnc + ld hl,dirloc ;dirloc=0ffh? + ld a,(hl) + rl a + ret nc ;yes, change it to 0 to mark as found - xra a ;dirloc=0 - mov m,a + xor a ;dirloc=0 + ld (hl),a ret search_fin: ;end of directory, or empty name - call set_end_dir ;may be artifical end - mvi a,255 - jmp sta_ret + call set_end_dir ;may be artifical end + ld a,255 + jp sta_ret delete: ;delete the currently addressed file - call check_write ;write protected? - mvi c,extnum ;search through file type + call check_write ;write protected? + ld c,extnum ;search through file type call search delete0: ;loop while directory matches - call end_of_dir ;stop if end - rz - ;set each non zero disk map entry to 0 + call end_of_dir ;stop if end + ret z + ;EQU each non zero disk map entry to 0 ;in the allocation vector ;may be r/o file - call check_rodir ;ro disk error if found - call getdptra ;HL=.buff(dptr) - mvi m,empty - mvi c,0 ;alloc elts set to 0 + call check_rodir ;ro disk error if found + call getdptra ;HL=.buff(dptr) + ld (hl),empty + ld c,0 ;alloc elts EQU to 0 call scandm - call wrdir ;write the directory - call searchn ;to next element - jmp delete0 ;for another record + call wrdir ;write the directory + call searchn ;to next element + jp delete0 ;for another record get_block: ;given allocation vector position BC, find the zero bit ;closest to this position by searching left and right. - ;if found, set the bit to one and return the bit position + ;if found, EQU the bit to one and return the bit position ;in hl. if not found (i.e., we pass 0 on the left, or ;maxall on the right), return 0000 in hl - mov d,b ;copy of starting position to de - mov e,c + ld d,b ;copy of starting position to de + ld e,c lefttst: - mov a,c ;skip if left=0000 - ora b - jz righttst + ld a,c ;skip if left=0000 + or b + jp z,righttst ;left not at position zero, bit zero? - dcx b ;left,right pushed - push d - push b + dec bc ;left,right pushed + push de + push bc call getallocbit - rar ;return block number if zero - jnc retblock + rr a ;return block number if zero + jp nc,retblock ;bit is one, so try the right - pop b ;left, right restored - pop d + pop bc ;left, right restored + pop de righttst: - lhld maxall ;value of maximum allocation# - mov a,e ;right=maxall? + ld hl,(maxall) ;value of maximum allocation# + ld a,e ;right=maxall? sub l - mov a,d - sbb h - jnc retblock0 ;return block 0000 if so - inx d ;left, right pushed - push b - push d - mov b,d ;ready right for call - mov c,e + ld a,d + sbc a,h + jp nc,retblock0 ;return block 0000 if so + inc de ;left, right pushed + push bc + push de + ld b,d ;ready right for call + ld c,e call getallocbit - rar ;return block number if zero - jnc retblock - pop d ;restore left and right pointers - pop b - jmp lefttst ;for another attempt + rr a ;return block number if zero + jp nc,retblock + pop de ;restore left and right pointers + pop bc + jp lefttst ;for another attempt retblock: - ral ;bit back into position and set to 1 - inr a + rl a ;bit back into position and EQU to 1 + inc a ;d contains the number of shifts required to reposition - call rotr ;move bit back to position and store - pop h ;HL returned value, DE discarded - pop d + call rotr ;move bit back to position and store + pop hl ;HL returned value, DE discarded + pop de ret retblock0: ;cannot find an available bit, return 0000 - mov a,c ; - ora b ;also at beginning - jnz lefttst - lxi h,0000h + ld a,c ; + or b ;also at beginning + jp nz,lefttst + ld hl,0000h ret copy_fcb: ;copy the entire file control block - mvi c,0 ;start at 0, to fcblen-1 - mvi e,fcblen + ld c,0 ;start at 0, to fcblen-1 + ld e,fcblen ; jmp copy_dir copy_dir: ;copy fcb information starting at C for E bytes ;into the currently addressed directory entry - push d ;save length for later - mvi b,0 ;double index to BC - lhld info ;HL = source for data - dad b ;DE=.fcb(C), source for copy - xchg - call getdptra ;HL=.buff(dptr), destination - pop b ;DE=source, HL=dest, C=length - call move ;data moved + push de ;save length for later + ld b,0 ;double index to BC + ld hl,(info) ;HL = source for data + add hl,bc ;DE=.fcb(C), source for copy + ex de,hl + call getdptra ;HL=.buff(dptr), destination + pop bc ;DE=source, HL=dest, C=length + call move ;data moved seek_copy: ;enter from close to seek and copy current element - call seek_dir ;to the directory element - jmp wrdir ;write the directory element + call seek_dir ;to the directory element + jp wrdir ;write the directory element ;ret @@ -1834,851 +1808,851 @@ rename: ;currently addressed file conrol block. the file ;name and type are changed, but the reel number ;is ignored. the user number is identical - call check_write ;may be write protected + call check_write ;may be write protected ;search up to the extent field - mvi c,extnum + ld c,extnum call search ;copy position 0 - lhld info ;HL=.fcb(0), A=fcb(0) - mov a,m - lxi d,dskmap ;HL=.fcb(dskmap) - dad d - mov m,a ;fcb(dskmap)=fcb(0) + ld hl,(info) ;HL=.fcb(0), A=fcb(0) + ld a,(hl) + ld de,dskmap ;HL=.fcb(dskmap) + add hl,de + ld (hl),a ;fcb(dskmap)=fcb(0) ;assume the same disk drive for new named file rename0: - call end_of_dir ;stop at end of dir - rz + call end_of_dir ;stop at end of dir + ret z ;not end of directory, rename next element - call check_rodir ;may be read-only file - mvi c,dskmap - mvi e,extnum + call check_rodir ;may be read-only file + ld c,dskmap + ld e,extnum call copy_dir ;element renamed, move to next call searchn - jmp rename0 + jp rename0 indicators: - ;set file indicators for current fcb - mvi c,extnum ;through file type + ;EQU file indicators for current fcb + ld c,extnum ;through file type call search indic0: - call end_of_dir ;stop at end of dir - rz + call end_of_dir ;stop at end of dir + ret z ;not end of directory, continue to change - mvi c,0 ;copy name - mvi e,extnum + ld c,0 ;copy name + ld e,extnum call copy_dir call searchn - jmp indic0 + jp indic0 open: ;search for the directory entry, copy to fcb - mvi c,namlen + ld c,namlen call search - call end_of_dir ;return with lret=255 if end - rz + call end_of_dir ;return with lret=255 if end + ret z ;not end of directory, copy fcb information open_copy: ;(referenced below to copy fcb info) - call getexta ;save extent# - mov a,m - push psw - push h - call getdptra ;DE = .buff(dptr) - xchg - lhld info ;HL=.fcb(0) - mvi c,nxtrec ;length of move operation - push d ;save .buff(dptr) - call move ;from .buff(dptr) to .fcb(0) + call getexta ;save extent# + ld a,(hl) + push af + push hl + call getdptra ;DE = .buff(dptr) + ex de,hl + ld hl,(info) ;HL=.fcb(0) + ld c,nxtrec ;length of move operation + push de ;save .buff(dptr) + call move ;from .buff(dptr) to .fcb(0) ;note that entire fcb is copied, including indicators - call setfwf ;sets file write flag - pop d ;HL=.buff(dptr+extnum) - lxi h,extnum - dad d - mov c,m ;C = directory extent number - lxi h,reccnt ;HL=.buff(dptr+reccnt) - dad d - mov b,m ;B holds directory record count - pop h ;restore extent number - pop psw - mov m,a + call setfwf ;sets file write flag + pop de ;HL=.buff(dptr+extnum) + ld hl,extnum + add hl,de + ld c,(hl) ;C = directory extent number + ld hl,reccnt ;HL=.buff(dptr+reccnt) + add hl,de + ld b,(hl) ;B holds directory record count + pop hl ;restore extent number + pop af + ld (hl),a ;HL = .user extent#, B = dir rec cnt, C = dir extent# ;if user ext < dir ext then user := 128 records ;if user ext = dir ext then user := dir records ;if user ext > dir ext then user := 0 records - mov a,c ;ready dir reccnt - cmp m - mov a,b - jz open_rcnt ;if same, user gets dir reccnt - mvi a,0 ;user is larger - jc open_rcnt - mvi a,128 ;directory is larger + ld a,c ;ready dir reccnt + cp (hl) + ld a,b + jp z,open_rcnt ;if same, user gets dir reccnt + ld a,0 ;user is larger + jp c,open_rcnt + ld a,128 ;directory is larger open_rcnt: ;A has record count to fill - lhld info - lxi d,reccnt - dad d - mov m,a + ld hl,(info) + ld de,reccnt + add hl,de + ld (hl),a ret mergezero: ;HL = .fcb1(i), DE = .fcb2(i), ;if fcb1(i) = 0 then fcb1(i) := fcb2(i) - mov a,m ;return if = 0000 - inx h - ora m - dcx h - rnz - ldax d ;low byte copied - mov m,a - inx d - inx h - ldax d ;back to input form - mov m,a - dcx d - dcx h + ld a,(hl) ;return if = 0000 + inc hl + or (hl) + dec hl + ret nz + ld a,(de) ;low byte copied + ld (hl),a + inc de + inc hl + ld a,(de) ;back to input form + ld (hl),a + dec de + dec hl ret close: ;locate the directory element and re-write it - xra a - sta lret - sta dcnt - sta dcnt+1 - call nowrite ;skip close if r/o disk - rnz + xor a + ld (lret),a + ld (dcnt),a + ld (dcnt+1),a + call nowrite ;skip close if r/o disk + ret nz ;check file write flag - 0 indicates written - call getmodnum ;fcb(modnum) in A - ani fwfmsk ;return if bit remains set - rnz - mvi c,namlen ;locate file + call getmodnum ;fcb(modnum) in A + and fwfmsk ;return if bit remains set + ret nz + ld c,namlen ;locate file call search - call end_of_dir ;return if not found - rz + call end_of_dir ;return if not found + ret z ;merge the disk map at info with that at buff(dptr) - lxi b,dskmap + ld bc,dskmap call getdptra - dad b ;DE is .buff(dptr+16) - xchg - lhld info ;DE=.buff(dptr+16), HL=.fcb(16) - dad b - mvi c,(fcblen-dskmap) ;length of single byte dm + add hl,bc ;DE is .buff(dptr+16) + ex de,hl + ld hl,(info) ;DE=.buff(dptr+16), HL=.fcb(16) + add hl,bc + ld c,(fcblen-dskmap) ;length of single byte dm merge0: - lda single ;skip to double - ora a - jz merged + ld a,(single) ;skip to double + or a + jp z,merged ;this is a single byte map ;if fcb(i) = 0 then fcb(i) = buff(i) ;if buff(i) = 0 then buff(i) = fcb(i) ;if fcb(i) <> buff(i) then error - mov a,m - ora a - ldax d - jnz fcbnzero + ld a,(hl) + or a + ld a,(de) + jp nz,fcbnzero ;fcb(i) = 0 - mov m,a ;fcb(i) = buff(i) + ld (hl),a ;fcb(i) = buff(i) fcbnzero: - ora a - jnz buffnzero + or a + jp nz,buffnzero ;buff(i) = 0 - mov a,m ;buff(i)=fcb(i) - stax d + ld a,(hl) ;buff(i)=fcb(i) + ld (de),a buffnzero: - cmp m ;fcb(i) = buff(i)? - jnz mergerr - jmp dmset ;if merge ok + cp (hl) ;fcb(i) = buff(i)? + jp nz,mergerr + jp dmset ;if merge ok merged: ;this is a double byte merge operation - call mergezero ;buff = fcb if buff 0000 - xchg ;fcb = buff if fcb 0000 + call mergezero ;buff = fcb if buff 0000 + ex de,hl ;fcb = buff if fcb 0000 call mergezero - xchg + ex de,hl ;they should be identical at this point - ldax d ;low same? - cmp m - jnz mergerr - inx d ;to high byte - inx h - ldax d ;high same? - cmp m - jnz mergerr + ld a,(de) ;low same? + cp (hl) + jp nz,mergerr + inc de ;to high byte + inc hl + ld a,(de) ;high same? + cp (hl) + jp nz,mergerr ;merge operation ok for this pair - dcr c ;extra count for double byte + dec c ;extra count for double byte dmset: - inx d ;to next byte position - inx h - dcr c ;for more - jnz merge0 + inc de ;to next byte position + inc hl + dec c ;for more + jp nz,merge0 ;end of disk map merge, check record count ;DE = .buff(dptr)+32, HL = .fcb(32) - lxi b,-(fcblen-extnum) - dad b - xchg - dad b + ld bc,-(fcblen-extnum) + add hl,bc + ex de,hl + add hl,bc ;DE = .fcb(extnum), HL = .buff(dptr+extnum) - ldax d ;current user extent number + ld a,(de) ;current user extent number ;if fcb(ext) >= buff(fcb) then ;buff(ext) := fcb(ext), buff(rec) := fcb(rec) - cmp m - jc endmerge + cp (hl) + jp c,endmerge ;fcb extent number >= dir extent number - mov m,a ;buff(ext) = fcb(ext) + ld (hl),a ;buff(ext) = fcb(ext) ;update directory record count field - lxi b,(reccnt-extnum) - dad b - xchg - dad b + ld bc,(reccnt-extnum) + add hl,bc + ex de,hl + add hl,bc ;DE=.buff(reccnt), HL=.fcb(reccnt) - mov a,m ;buff(reccnt)=fcb(reccnt) - stax d + ld a,(hl) ;buff(reccnt)=fcb(reccnt) + ld (de),a endmerge: - mvi a,_true ;mark as copied - sta fcb_copied - jmp seek_copy ;ok to "wrdir" here - 1.4 compat + ld a,_true ;mark as copied + ld (fcb_copied),a + jp seek_copy ;ok to "wrdir" here - 1.4 compat ; ret mergerr: ;elements did not merge correctly - lxi h,lret ;=255 non zero flag set - dcr m + ld hl,lret ;=255 non zero flag set + dec (hl) ret make: ;create a new file by creating a directory entry ;then opening the file - call check_write ;may be write protected - lhld info ;save fcb address, look for e5 - push h - lxi h,efcb ;info = .empty - shld info - mvi c,1 ;length 1 match on empty entry + call check_write ;may be write protected + ld hl,(info) ;save fcb address, look for e5 + push hl + ld hl,efcb ;info = .empty + ld (info),hl + ld c,1 ;length 1 match on empty entry call search - call end_of_dir ;zero flag set if no space - pop h ;recall info address - shld info ;in case we return here - rz ;return with error condition 255 if not found - xchg ;DE = info address + call end_of_dir ;zero flag EQU if no space + pop hl ;recall info address + ld (info),hl ;in case we return here + ret z ;return with error condition 255 if not found + ex de,hl ;DE = info address ;clear the remainder of the fcb - lxi h,namlen ;HL=.fcb(namlen) - dad d - mvi c,fcblen-namlen ;number of bytes to fill - xra a ;clear accumulator to 00 for fill + ld hl,namlen ;HL=.fcb(namlen) + add hl,de + ld c,fcblen-namlen ;number of bytes to fill + xor a ;clear accumulator to 00 for fill make0: - mov m,a - inx h - dcr c - jnz make0 - lxi h,ubytes ;HL = .fcb(ubytes) - dad d - mov m,a ;fcb(ubytes) = 0 - call setcdr ;may have extended the directory + ld (hl),a + inc hl + dec c + jp nz,make0 + ld hl,ubytes ;HL = .fcb(ubytes) + add hl,de + ld (hl),a ;fcb(ubytes) = 0 + call setcdr ;may have extended the directory ;now copy entry to the directory call copy_fcb - ;and set the file write flag to "1" - jmp setfwf + ;and EQU the file write flag to "1" + jp setfwf ;ret open_reel: ;close the current extent, and open the next one ;if possible. RMF is true if in read mode - xra a ;set true if actually copied - sta fcb_copied - call close ;close current extent + xor a ;EQU true if actually copied + ld (fcb_copied),a + call close ;close current extent ;lret remains at enddir if we cannot open the next ext - call end_of_dir ;return if end - rz + call end_of_dir ;return if end + ret z ;increment extent number - lhld info ;HL=.fcb(extnum) - lxi b,extnum - dad b - mov a,m ;fcb(extnum)=++1 - inr a - ani maxext - mov m,a - jz open_mod ;move to next module if zero + ld hl,(info) ;HL=.fcb(extnum) + ld bc,extnum + add hl,bc + ld a,(hl) ;fcb(extnum)=++1 + inc a + and maxext + ld (hl),a + jp z,open_mod ;move to next module if zero ;may be in the same extent group - mov b,a - lda extmsk - ana b + ld b,a + ld a,(extmsk) + and b ;if result is zero, then not in the same group - lxi h,fcb_copied ;true if the fcb was copied to directory - ana m ;produces a 00 in accumulator if not written - jz open_reel0 ;go to next physical extent + ld hl,fcb_copied ;true if the fcb was copied to directory + and (hl) ;produces a 00 in accumulator if not written + jp z,open_reel0 ;go to next physical extent ;result is non zero, so we must be in same logical ext - jmp open_reel1 ;to copy fcb information + jp open_reel1 ;to copy fcb information open_mod: ;extent number overflow, go to next module - lxi b,(modnum-extnum) ;HL=.fcb(modnum) - dad b - inr m ;fcb(modnum)=++1 + ld bc,(modnum-extnum) ;HL=.fcb(modnum) + add hl,bc + inc (hl) ;fcb(modnum)=++1 ;module number incremented, check for overflow - mov a,m ;mask high order bits - ani maxmod - jz open_r_err ;cannot overflow to zero + ld a,(hl) ;mask high order bits + and maxmod + jp z,open_r_err ;cannot overflow to zero ;otherwise, ok to continue with new module open_reel0: - mvi c,namlen ;next extent found? + ld c,namlen ;next extent found? call search call end_of_dir - jnz open_reel1 + jp nz,open_reel1 ;end of file encountered - lda rmf ;0ffh becomes 00 if read - inr a - jz open_r_err ;sets lret = 1 + ld a,(rmf) ;0ffh becomes 00 if read + inc a + jp z,open_r_err ;sets lret = 1 ;try to extend the current file call make ;cannot be end of directory call end_of_dir - jz open_r_err ;with lret = 1 - jmp open_reel2 + jp z,open_r_err ;with lret = 1 + jp open_reel2 open_reel1: ;not end of file, open call open_copy open_reel2: - call getfcb ;set parameters - xra a ;lret = 0 - jmp sta_ret + call getfcb ;EQU parameters + xor a ;lret = 0 + jp sta_ret ; ret ;with lret = 0 open_r_err: ;cannot move to next extent of this file - call setlret1 ;lret = 1 - jmp setfwf ;ensure that it will not be closed + call setlret1 ;lret = 1 + jp setfwf ;ensure that it will not be closed ;ret seqdiskread: ;sequential disk read operation - mvi a,1 - sta seqio + ld a,1 + ld (seqio),a ;drop through to diskread diskread: ;(may enter from seqdiskread) - mvi a,_true ;read mode flag = true (open_reel) - sta rmf + ld a,_true ;read mode flag = true (open_reel) + ld (rmf),a ;read the next record from the current fcb - call getfcb ;sets parameters for the read - lda vrecord ;vrecord-rcount - lxi h,rcount - cmp m + call getfcb ;sets parameters for the read + ld a,(vrecord) ;vrecord-rcount + ld hl,rcount + cp (hl) ;skip if rcount > vrecord - jc recordok + jp c,recordok ;not enough records in the extent ;record count must be 128 to continue - cpi 128 ;vrecord = 128? - jnz diskeof ;skip if vrecord<>128 - call open_reel ;go to next extent if so - xra a ;vrecord=00 - sta vrecord + cp 128 ;vrecord = 128? + jp nz,diskeof ;skip if vrecord<>128 + call open_reel ;go to next extent if so + xor a ;vrecord=00 + ld (vrecord),a ;now check for open ok - lda lret ;stop at eof - ora a - jnz diskeof + ld a,(lret) ;stop at eof + or a + jp nz,diskeof recordok: ;arrive with fcb addressing a record to read call index ;error 2 if reading unwritten data ;(returns 1 to be compatible with 1.4) - call allocated ;arecord=0000? - jz diskeof + call allocated ;arecord=0000? + jp z,diskeof ;record has been allocated, read it - call atran ;arecord now a disk address - call seek ;to proper track,sector - call rdbuff ;to dma address - jmp setfcb ;replace parameter + call atran ;arecord now a disk address + call seek ;to proper track,sector + call rdbuff ;to dma address + jp setfcb ;replace parameter ; ret diskeof: - jmp setlret1 ;lret = 1 + jp setlret1 ;lret = 1 ;ret seqdiskwrite: ;sequential disk write - mvi a,1 - sta seqio + ld a,1 + ld (seqio),a ;drop through to diskwrite diskwrite: ;(may enter here from seqdiskwrite above) - mvi a,_false ;read mode flag - sta rmf + ld a,_false ;read mode flag + ld (rmf),a ;write record to currently selected file - call check_write ;in case write protected - lhld info ;HL = .fcb(0) - call check_rofile ;may be a read-only file - call getfcb ;to set local parameters - lda vrecord ;vrecord-128 - cpi lstrec+1 + call check_write ;in case write protected + ld hl,(info) ;HL = .fcb(0) + call check_rofile ;may be a read-only file + call getfcb ;to EQU local parameters + ld a,(vrecord) ;vrecord-128 + cp lstrec+1 ;skip if vrecord > lstrec ;vrecord = 128, cannot open next extent - jnc setlret1 ;lret=1 + jp nc,setlret1 ;lret=1 diskwr0: ;can write the next record, so continue call index call allocated - mvi c,0 ;marked as normal write operation for wrbuff - jnz diskwr1 + ld c,0 ;marked as normal write operation for wrbuff + jp nz,diskwr1 ;not allocated ;the argument to getblock is the starting ;position for the disk search, and should be ;the last allocated block for this file, or ;the value 0 if no space has been allocated call dm_position - sta dminx ;save for later - lxi b,0000h ;may use block zero - ora a ;skip if no previous block - jz nopblock + ld (dminx),a ;save for later + ld bc,0000h ;may use block zero + or a ;skip if no previous block + jp z,nopblock ;previous block exists at A - mov c,a ;previous block # in BC - dcx b - call getdm ;previous block # to HL - mov b,h ;BC=prev block# - mov c,l + ld c,a ;previous block # in BC + dec bc + call getdm ;previous block # to HL + ld b,h ;BC=prev block# + ld c,l nopblock: ;BC = 0000, or previous block # - call get_block ;block # to HL + call get_block ;block # to HL ;arrive here with block# or zero - mov a,l - ora h - jnz blockok + ld a,l + or h + jp nz,blockok ;cannot find a block to allocate - mvi a,2 ;lret=2 - jmp sta_ret + ld a,2 ;lret=2 + jp sta_ret blockok: ;allocated block number is in HL - shld arecord - xchg ;block number to DE - lhld info ;HL=.fcb(dskmap) - lxi b,dskmap - dad b - lda single ;set flags for single byte dm - ora a - lda dminx ;recall dm index - jz allocwd ;skip if allocating word + ld (arecord),hl + ex de,hl ;block number to DE + ld hl,(info) ;HL=.fcb(dskmap) + ld bc,dskmap + add hl,bc + ld a,(single) ;EQU flags for single byte dm + or a + ld a,(dminx) ;recall dm index + jp z,allocwd ;skip if allocating word ;allocating a byte value - call addh ;single byte alloc - mov m,e - jmp diskwru ;to continue + call addh ;single byte alloc + ld (hl),e + jp diskwru ;to continue allocwd: ;allocate a word value - mov c,a ;double(dminx) - mvi b,0 - dad b ;HL=.fcb(dminx*2) - dad b - mov m,e ;double wd - inx h - mov m,d + ld c,a ;double(dminx) + ld b,0 + add hl,bc ;HL=.fcb(dminx*2) + add hl,bc + ld (hl),e ;double wd + inc hl + ld (hl),d diskwru: ;disk write to previously unallocated block - mvi c,2 ;marked as unallocated write + ld c,2 ;marked as unallocated write diskwr1: ;continue the write operation of no allocation error ;C = 0 if normal write, 2 if to prev unalloc block - lda lret ;stop if non zero returned value - ora a - rnz - push b ;save write flag - call atran ;arecord set - lda seqio - dcr a - dcr a - jnz diskwr11 - pop b - push b - mov a,c - dcr a - dcr a - jnz diskwr11 ;old allocation - push h ;arecord in hl ret from atran - lhld buffa ;zero buffa & fill - mov d,a -fill0: mov m,a - inx h - inr d - jp fill0 + ld a,(lret) ;stop if non zero returned value + or a + ret nz + push bc ;save write flag + call atran ;arecord set + ld a,(seqio) + dec a + dec a + jp nz,diskwr11 + pop bc + push bc + ld a,c + dec a + dec a + jp nz,diskwr11 ;old allocation + push hl ;arecord in hl ret from atran + ld hl,(buffa) ;zero buffa & fill + ld d,a +fill0: ld (hl),a + inc hl + inc d + jp p,fill0 call setdir - lhld arecord1 - mvi c,2 -fill1: shld arecord - push b + ld hl,(arecord1) + ld c,2 +fill1: ld (arecord),hl + push bc call seek - pop b - call wrbuff ;write fill record - lhld arecord ;restore last record - mvi c,0 ;change allocate flag - lda blkmsk - mov b,a - ana l - cmp b - inx h - jnz fill1 ;cont until cluster is zeroed - pop h - shld arecord + pop bc + call wrbuff ;write fill record + ld hl,(arecord) ;restore last record + ld c,0 ;change allocate flag + ld a,(blkmsk) + ld b,a + and l + cp b + inc hl + jp nz,fill1 ;cont until cluster is zeroed + pop hl + ld (arecord),hl call setdata diskwr11: call seek ;to proper file position - pop b ;restore/save write flag (C=2 if new block) - push b - call wrbuff ;written to disk - pop b ;C = 2 if a new block was allocated, 0 if not + pop bc ;restore/save write flag (C=2 if new block) + push bc + call wrbuff ;written to disk + pop bc ;C = 2 if a new block was allocated, 0 if not ;increment record count if rcount<=vrecord - lda vrecord ;vrecord-rcount - lxi h,rcount - cmp m - jc diskwr2 + ld a,(vrecord) ;vrecord-rcount + ld hl,rcount + cp (hl) + jp c,diskwr2 ;rcount <= vrecord - mov m,a ;rcount = vrecord+1 - inr m - mvi c,2 ;mark as record count incremented + ld (hl),a ;rcount = vrecord+1 + inc (hl) + ld c,2 ;mark as record count incremented diskwr2: if patch1 ; CP/M V2.2 patch 1 for use of optional blocking/deblocking nop nop - lxi h,0 + ld hl,0 else ; original code ;A has vrecord, C=2 if new block or new record# - dcr c - dcr c - jnz noupdate + dec c + dec c + jp nz,noupdate endif - push psw ;save vrecord value - call getmodnum ;HL=.fcb(modnum), A=fcb(modnum) - ;reset the file write flag to mark as written fcb - ani (~fwfmsk)&0ffh ;bit reset - mov m,a ;fcb(modnum) = fcb(modnum) and 7fh - pop psw ;restore vrecord + push af ;save vrecord value + call getmodnum ;HL=.fcb(modnum), A=fcb(modnum) + ;reEQU the file write flag to mark as written fcb + and (~fwfmsk)&0ffh ;bit reset + ld (hl),a ;fcb(modnum) = fcb(modnum) and 7fh + pop af ;restore vrecord noupdate: ;check for end of extent, if found attempt to open ;next extent in preparation for next write - cpi lstrec ;vrecord=lstrec? - jnz diskwr3 ;skip if not + cp lstrec ;vrecord=lstrec? + jp nz,diskwr3 ;skip if not ;may be random access write, if so we are done ;change next - lda seqio ;skip next extent open op - cpi 1 - jnz diskwr3 + ld a,(seqio) ;skip next extent open op + cp 1 + jp nz,diskwr3 ;update current fcb before going to next extent call setfcb - call open_reel ;rmf=false + call open_reel ;rmf=false ;vrecord remains at lstrec causing eof if ;no more directory space is available - lxi h,lret - mov a,m - ora a - jnz nospace - ;space available, set vrecord=255 - dcr a ;goes to 00 next time - sta vrecord + ld hl,lret + ld a,(hl) + or a + jp nz,nospace + ;space available, EQU vrecord=255 + dec a ;goes to 00 next time + ld (vrecord),a nospace: - mvi m,0 ;lret = 00 for returned value + ld (hl),0 ;lret = 00 for returned value diskwr3: - jmp setfcb ;replace parameters + jp setfcb ;replace parameters ;ret rseek: ;random access seek operation, C=0ffh if read mode ;fcb is assumed to address an active file control block - ;(modnum has been set to 1100_0000b if previous bad seek) - xra a ;marked as random access operation - sta seqio + ;(modnum has been EQU to 1100_0000b if previous bad seek) + xor a ;marked as random access operation + ld (seqio),a rseek1: - push b ;save r/w flag - lhld info ;DE will hold base of fcb - xchg - lxi h,ranrec ;HL=.fcb(ranrec) - dad d - mov a,m ;record number - ani 7fh - push psw - mov a,m ;cy=lsb of extent# - ral - inx h ;A=ext# - mov a,m - ral - ani 11111b - mov c,a ;C holds extent number, record stacked - mov a,m ;mod# - rar - rar - rar - rar - ani 1111b - mov b,a ;B holds module#, C holds ext# - pop psw ;recall sought record # + push bc ;save r/w flag + ld hl,(info) ;DE will hold base of fcb + ex de,hl + ld hl,ranrec ;HL=.fcb(ranrec) + add hl,de + ld a,(hl) ;record number + and 7fh + push af + ld a,(hl) ;cy=lsb of extent# + rl a + inc hl ;A=ext# + ld a,(hl) + rl a + and 11111b + ld c,a ;C holds extent number, record stacked + ld a,(hl) ;mod# + rr a + rr a + rr a + rr a + and 1111b + ld b,a ;B holds module#, C holds ext# + pop af ;recall sought record # ;check to insure that high byte of ran rec = 00 - inx h ;l=high byte (must be 00) - mov l,m - inr l ;zero flag, l=6 - dcr l - mvi l,6 + inc hl ;l=high byte (must be 00) + ld l,(hl) + inc l ;zero flag, l=6 + dec l + ld l,6 ;produce error 6, seek past physical eod - jnz seekerr + jp nz,seekerr ;otherwise, high byte = 0, A = sought record - lxi h,nxtrec ;HL = .fcb(nxtrec) - dad d - mov m,a ;sought rec# stored away + ld hl,nxtrec ;HL = .fcb(nxtrec) + add hl,de + ld (hl),a ;sought rec# stored away ;arrive here with B=mod#, C=ext#, DE=.fcb, rec stored ;the r/w flag is still stacked. compare fcb values - lxi h,extnum ;A=seek ext# - dad d - mov a,c - sub m ;tests for = extents - jnz ranclose + ld hl,extnum ;A=seek ext# + add hl,de + ld a,c + sub (hl) ;tests for = extents + jp nz,ranclose ;extents match, check mod# - lxi h,modnum ;B=seek mod# - dad d - mov a,b + ld hl,modnum ;B=seek mod# + add hl,de + ld a,b ;could be overflow at eof, producing module# ;of 90H or 10H, so compare all but fwf - sub m ;same? - ani 7fh - jz seekok + sub (hl) ;same? + and 7fh + jp z,seekok ranclose: - push b ;save seek mod#,ext#, .fcb - push d - call close ;current extent closed - pop d ;recall parameters and fill - pop b - mvi l,3 ;cannot close error #3 - lda lret - inr a - jz badseek - lxi h,extnum ;fcb(extnum)=ext# - dad d - mov m,c - lxi h,modnum ;fcb(modnum)=mod# - dad d - mov m,b - call open ;is the file present? - lda lret ;open successful? - inr a - jnz seekok + push bc ;save seek mod#,ext#, .fcb + push de + call close ;current extent closed + pop de ;recall parameters and fill + pop bc + ld l,3 ;cannot close error #3 + ld a,(lret) + inc a + jp z,badseek + ld hl,extnum ;fcb(extnum)=ext# + add hl,de + ld (hl),c + ld hl,modnum ;fcb(modnum)=mod# + add hl,de + ld (hl),b + call open ;is the file present? + ld a,(lret) ;open successful? + inc a + jp nz,seekok ;cannot open the file, read mode? - pop b ;r/w flag to c (=0ffh if read) - push b ;everyone expects this item stacked - mvi l,4 ;seek to unwritten extent #4 - inr c ;becomes 00 if read operation - jz badseek ;skip to error if read operation + pop bc ;r/w flag to c (=0ffh if read) + push bc ;everyone expects this item stacked + ld l,4 ;seek to unwritten extent #4 + inc c ;becomes 00 if read operation + jp z,badseek ;skip to error if read operation ;write operation, make new extent call make - mvi l,5 ;cannot create new extent #5 - lda lret ;no dir space - inr a - jz badseek + ld l,5 ;cannot create new extent #5 + ld a,(lret) ;no dir space + inc a + jp z,badseek ;file make operation successful seekok: - pop b ;discard r/w flag - xra a ;with zero set - jmp sta_ret + pop bc ;discard r/w flag + xor a ;with zero set + jp sta_ret badseek: ;fcb no longer contains a valid fcb, mark ;with 1100_000b in modnum field so that it ;appears as overflow with file write flag set - push h ;save error flag - call getmodnum ;HL = .modnum - mvi m,11000000b - pop h ;and drop through + push hl ;save error flag + call getmodnum ;HL = .modnum + ld (hl),11000000b + pop hl ;and drop through seekerr: - pop b ;discard r/w flag - mov a,l ;lret=#, nonzero - sta lret + pop bc ;discard r/w flag + ld a,l ;lret=#, nonzero + ld (lret),a ;setfwf returns non-zero accumulator for err - jmp setfwf ;flag set, so subsequent close ok + jp setfwf ;flag set, so subsequent close ok ;ret randiskread: ;random disk read operation - mvi c,_true ;marked as read operation + ld c,_true ;marked as read operation call rseek - cz diskread ;if seek successful + call z,diskread ;if seek successful ret randiskwrite: ;random disk write operation - mvi c,_false ;marked as write operation + ld c,_false ;marked as write operation call rseek - cz diskwrite ;if seek successful + call z,diskwrite ;if seek successful ret compute_rr: ;compute random record position for getfilesize/setrandom - xchg - dad d + ex de,hl + add hl,de ;DE=.buf(dptr) or .fcb(0), HL = .f(nxtrec/reccnt) - mov c,m ;BC = 0000 0000 ?rrr rrrr - mvi b,0 - lxi h,extnum ;A=e000 0000 - dad d - mov a,m - rrc - ani 80h - add c - mov c,a - mvi a,0 - adc b - mov b,a + ld c,(hl) ;BC = 0000 0000 ?rrr rrrr + ld b,0 + ld hl,extnum ;A=e000 0000 + add hl,de + ld a,(hl) + rrca + and 80h + add a,c + ld c,a + ld a,0 + adc a,b + ld b,a ;BC = 0000 000? errrr rrrr - mov a,m - rrc - ani 0fh - add b - mov b,a + ld a,(hl) + rrca + and 0fh + add a,b + ld b,a ;BC = 000? eeee errrr rrrr - lxi h,modnum ;A=XXX? mmmm - dad d - mov a,m - add a ;cy=? A=mmmm 0000 - add a - add a - add a - push psw - add b - mov b,a + ld hl,modnum ;A=XXX? mmmm + add hl,de + ld a,(hl) + add a,a ;cy=? A=mmmm 0000 + add a,a + add a,a + add a,a + push af + add a,b + ld b,a ;cy=?, BC = mmmm eeee errr rrrr - push psw ;possible second carry - pop h ;cy = lsb of L - mov a,l ;cy = lsb of A - pop h ;cy = lsb of L - ora l ;cy/cy = lsb of A - ani 1 ;A = 0000 000? possible carry-out + push af ;possible second carry + pop hl ;cy = lsb of L + ld a,l ;cy = lsb of A + pop hl ;cy = lsb of L + or l ;cy/cy = lsb of A + and 1 ;A = 0000 000? possible carry-out ret getfilesize: ;compute logical file size for current fcb - mvi c,extnum + ld c,extnum call search ;zero the receiving ranrec field - lhld info ;save position - lxi d,ranrec - dad d - push h - mov m,d ;=00 00 00 - inx h - mov m,d - inx h - mov m,d + ld hl,(info) ;save position + ld de,ranrec + add hl,de + push hl + ld (hl),d ;=00 00 00 + inc hl + ld (hl),d + inc hl + ld (hl),d getsize: call end_of_dir - jz setsize + jp z,setsize ;current fcb addressed by dptr - call getdptra ;ready for compute size - lxi d,reccnt + call getdptra ;ready for compute size + ld de,reccnt call compute_rr ;A=0000 000? BC = mmmm eeee errr rrrr ;compare with memory, larger? - pop h ;recall, replace .fcb(ranrec) - push h - mov e,a ;save cy - mov a,c ;ls byte - sub m - inx h - mov a,b ;middle byte - sbb m - inx h - mov a,e ;carry if .fcb(ranrec) > directory - sbb m - jc getnextsize ;for another try + pop hl ;recall, replace .fcb(ranrec) + push hl + ld e,a ;save cy + ld a,c ;ls byte + sub (hl) + inc hl + ld a,b ;middle byte + sbc a,(hl) + inc hl + ld a,e ;carry if .fcb(ranrec) > directory + sbc a,(hl) + jp c,getnextsize ;for another try ;fcb is less or equal, fill from directory - mov m,e - dcx h - mov m,b - dcx h - mov m,c + ld (hl),e + dec hl + ld (hl),b + dec hl + ld (hl),c getnextsize: call searchn - jmp getsize + jp getsize setsize: - pop h ;discard .fcb(ranrec) + pop hl ;discard .fcb(ranrec) ret setrandom: - ;set random record from the current file control block - lhld info ;ready params for computesize - lxi d,nxtrec - call compute_rr ;DE=info, A=cy, BC=mmmm eeee errr rrrr - lxi h,ranrec ;HL = .fcb(ranrec) - dad d - mov m,c ;to ranrec - inx h - mov m,b - inx h - mov m,a + ;EQU random record from the current file control block + ld hl,(info) ;ready params for computesize + ld de,nxtrec + call compute_rr ;DE=info, A=cy, BC=mmmm eeee errr rrrr + ld hl,ranrec ;HL = .fcb(ranrec) + add hl,de + ld (hl),c ;to ranrec + inc hl + ld (hl),b + inc hl + ld (hl),a ret select: ;select disk info for subsequent input or output ops - lhld dlog - lda curdsk - mov c,a + ld hl,(dlog) + ld a,(curdsk) + ld c,a call hlrotr - push h ;save it for test below, send to seldsk - xchg - call selectdisk ;recall dlog vector - pop h - cz sel_error ;returns true if select ok + push hl ;save it for test below, send to seldsk + ex de,hl + call selectdisk ;recall dlog vector + pop hl + call z,sel_error ;returns true if select ok ;is the disk logged in? - mov a,l ;return if bit is set - rar - rc - ;disk not logged in, set bit and initialize - lhld dlog ;call ready - mov c,l - mov b,h - call set_cdisk ;dlog=set_cdisk(dlog) - shld dlog - jmp initialize + ld a,l ;return if bit is set + rr a + ret c + ;disk not logged in, EQU bit and initialize + ld hl,(dlog) ;call ready + ld c,l + ld b,h + call set_cdisk ;dlog=set_cdisk(dlog) + ld (dlog),hl + jp initialize ;ret curselect: - lda linfo ;skip if linfo=curdsk - lxi h,curdsk - cmp m - rz - mov m,a ;curdsk=info - jmp select + ld a,(linfo) ;skip if linfo=curdsk + ld hl,curdsk + cp (hl) + ret z + ld (hl),a ;curdsk=info + jp select ;ret reselect: ;check current fcb to see if reselection necessary - mvi a,_true ;mark possible reselect - sta resel - lhld info ;drive select code - mov a,m - ani 11111b ;non zero is auto drive select - dcr a ;drive code normalized to 0..30, or 255 - sta linfo ;save drive code - cpi 30 - jnc noselect + ld a,_true ;mark possible reselect + ld (resel),a + ld hl,(info) ;drive select code + ld a,(hl) + and 11111b ;non zero is auto drive select + dec a ;drive code normalized to 0..30, or 255 + ld (linfo),a ;save drive code + cp 30 + jp nc,noselect ;auto select function, save curdsk - lda curdsk ;olddsk=curdsk - sta olddsk - mov a,m ;save drive code - sta fcbdsk - ani 11100000b ;preserve hi bits - mov m,a + ld a,(curdsk) ;olddsk=curdsk + ld (olddsk),a + ld a,(hl) ;save drive code + ld (fcbdsk),a + and 11100000b ;preserve hi bits + ld (hl),a call curselect noselect: - ;set user code - lda usrcode ;0...31 - lhld info - ora m - mov m,a + ;EQU user code + ld a,(usrcode) ;0...31 + ld hl,(info) + or (hl) + ld (hl),a ret ; individual function handlers func12: ;return version number - mvi a,dvers ;lret = dvers (high = 00) - jmp sta_ret + ld a,dvers ;lret = dvers (high = 00) + jp sta_ret ; ret ;jmp goback func13: - ;reset disk system - initialize to disk 0 - lxi h,0 - shld rodsk - shld dlog - xra a ;note that usrcode remains unchanged - sta curdsk - lxi h,tbuff ;dmaad = tbuff - shld dmaad - call setdata ;to data dma address - jmp select + ;reEQU disk system - initialize to disk 0 + ld hl,0 + ld (rodsk),hl + ld (dlog),hl + xor a ;note that usrcode remains unchanged + ld (curdsk),a + ld hl,tbuff ;dmaad = tbuff + ld (dmaad),hl + call setdata ;to data dma address + jp select ;ret ;jmp goback func14 equ curselect @@ -2687,101 +2661,101 @@ func14 equ curselect func15: ;open file - call clrmodnum ;clear the module number + call clrmodnum ;clear the module number call reselect - jmp open + jp open ;ret ;jmp goback func16: ;close file call reselect - jmp close + jp close ;ret ;jmp goback func17: ;search for first occurrence of a file - mvi c,0 ;length assuming '?' true - xchg ;was lhld info - mov a,m ;no reselect if ? - cpi '?' - jz qselect ;skip reselect if so + ld c,0 ;length assuming '?' true + ex de,hl ;was lhld info + ld a,(hl) ;no reselect if ? + cp '?' + jp z,qselect ;skip reselect if so ;normal search call getexta - mov a,m - cpi '?' - cnz clrmodnum ;module number zeroed + ld a,(hl) + cp '?' + call nz,clrmodnum ;module number zeroed call reselect - mvi c,namlen + ld c,namlen qselect: call search - jmp dir_to_user ;copy directory entry to user + jp dir_to_user ;copy directory entry to user ;ret ;jmp goback func18: ;search for next occurrence of a file name - lhld searcha - shld info + ld hl,(searcha) + ld (info),hl call reselect call searchn - jmp dir_to_user ;copy directory entry to user + jp dir_to_user ;copy directory entry to user ;ret ;jmp goback func19: ;delete a file call reselect call delete - jmp copy_dirloc + jp copy_dirloc ;ret ;jmp goback func20: ;read a file call reselect - jmp seqdiskread ; + jp seqdiskread ; ;jmp goback func21: ;write a file call reselect - jmp seqdiskwrite ; + jp seqdiskwrite ; ;jmp goback func22: ;make a file call clrmodnum call reselect - jmp make + jp make ;ret ;jmp goback func23: ;rename a file call reselect call rename - jmp copy_dirloc + jp copy_dirloc ;ret ;jmp goback func24: ;return the login vector - lhld dlog - jmp sthl_ret ; + ld hl,(dlog) + jp sthl_ret ; ; ret ;jmp goback func25: ;return selected disk number - lda curdsk - jmp sta_ret + ld a,(curdsk) + jp sta_ret ; ret ;jmp goback func26: - ;set the subsequent dma address to info - xchg ;was lhld info - shld dmaad ;dmaad = info - jmp setdata ;to data dma address + ;EQU the subsequent dma address to info + ex de,hl ;was lhld info + ld (dmaad),hl ;dmaad = info + jp setdata ;to data dma address ;ret ;jmp goback func27: ;return the login vector address - lhld alloca - jmp sthl_ret + ld hl,(alloca) + jp sthl_ret ; ret ;jmp goback func28 equ set_ro @@ -2790,109 +2764,109 @@ func28 equ set_ro func29: ;return r/o bit vector - lhld rodsk - jmp sthl_ret + ld hl,(rodsk) + jp sthl_ret ; ret ;jmp goback func30: - ;set file indicators + ;EQU file indicators call reselect call indicators - jmp copy_dirloc ;lret=dirloc + jp copy_dirloc ;lret=dirloc ;ret ;jmp goback func31: ;return address of disk parameter block - lhld dpbaddr + ld hl,(dpbaddr) sthl_ret: - shld aret - ret ;jmp goback + ld (aret),hl + ret ;jmp goback func32: - ;set user code - lda linfo - cpi 0ffh - jnz setusrcode + ;EQU user code + ld a,(linfo) + cp 0ffh + jp nz,setusrcode ;interrogate user code instead - lda usrcode ;lret=usrcode - jmp sta_ret + ld a,(usrcode) ;lret=usrcode + jp sta_ret ; ret ;jmp goback setusrcode: - ani 1fh - sta usrcode - ret ;jmp goback + and 1fh + ld (usrcode),a + ret ;jmp goback ; func33: ;random disk read operation call reselect - jmp randiskread ;to perform the disk read + jp randiskread ;to perform the disk read ;ret ;jmp goback ; func34: ;random disk write operation call reselect - jmp randiskwrite ;to perform the disk write + jp randiskwrite ;to perform the disk write ;ret ;jmp goback ; func35: ;return file size (0-65536) call reselect - jmp getfilesize + jp getfilesize ;ret ;jmp goback ; -func36 equ setrandom ; - ;set random record +func36 equ setrandom ; + ;EQU random record ;ret ;jmp goback func37: ; - lhld info - mov a,l - cma - mov e,a - mov a,h - cma - lhld dlog - ana h - mov d,a - mov a,l - ana e - mov e,a - lhld rodsk - xchg - shld dlog - mov a,l - ana e - mov l,a - mov a,h - ana d - mov h,a - shld rodsk + ld hl,(info) + ld a,l + cpl + ld e,a + ld a,h + cpl + ld hl,(dlog) + and h + ld d,a + ld a,l + and e + ld e,a + ld hl,(rodsk) + ex de,hl + ld (dlog),hl + ld a,l + and e + ld l,a + ld a,h + and d + ld h,a + ld (rodsk),hl ret ; ; goback: ;arrive here at end of processing to return to user - lda resel - ora a - jz retmon + ld a,(resel) + or a + jp z,retmon ;reselection may have taken place - lhld info ;fcb(0)=0 - mvi m,0 - lda fcbdsk - ora a - jz retmon + ld hl,(info) ;fcb(0)=0 + ld (hl),0 + ld a,(fcbdsk) + or a + jp z,retmon ;restore disk number - mov m,a ;fcb(0)=fcbdsk - lda olddsk - sta linfo + ld (hl),a ;fcb(0)=fcbdsk + ld a,(olddsk) + ld (linfo),a call curselect ; ; return from the disk monitor retmon: - lhld entsp ;user stack restored - sphl - lhld aret ;BA = HL = aret - mov a,l - mov b,h + ld hl,(entsp) ;user stack restored + ld sp,hl + ld hl,(aret) ;BA = HL = aret + ld a,l + ld b,h ret func38 equ func_ret @@ -2901,11 +2875,11 @@ func39 equ func_ret func40: ;random disk write with zero fill of unallocated block call reselect - mvi a,2 - sta seqio - mvi c,_false + ld a,2 + ld (seqio),a + ld c,_false call rseek1 - cz diskwrite ;if seek successful + call z,diskwrite ;if seek successful ret @@ -2917,7 +2891,7 @@ rodsk: dw 0 ;read only disk vector dlog: dw 0 ;logged-in disks dmaad: dw tbuff ;initial dma address -; curtrka - alloca are set upon disk select +; curtrka - alloca are EQU upon disk select ; (data must be adjacent, do not insert variables) ; (address of translate vector, not used) cdrmaxa:ds word ;pointer to cur dir max value @@ -2927,9 +2901,9 @@ buffa: ds word ;pointer to directory dma address dpbaddr:ds word ;current disk parameter block address checka: ds word ;current checksum vector address alloca: ds word ;current allocation vector address -addlist equ $-buffa ;address list size +addlist equ $-buffa ;address list size -; sectpt - offset obtained from disk parm block at dpbaddr +; sectpt - offEQU obtained from disk parm block at dpbaddr ; (data must be adjacent, do not insert variables) sectpt: ds word ;sectors per track blkshf: ds byte ;block shift factor @@ -2939,13 +2913,13 @@ maxall: ds word ;maximum allocation number dirmax: ds word ;largest directory number dirblk: ds word ;reserved allocation bits for directory chksiz: ds word ;size of checksum vector -offset: ds word ;offset tracks at beginning -dpblist equ $-sectpt ;size of area +offset: ds word ;offEQU tracks at beginning +dpblist equ $-sectpt ;size of area ; local variables tranv: ds word ;address of translate vector fcb_copied: - ds byte ;set true if copy_fcb called + ds byte ;EQU true if copy_fcb called rmf: ds byte ;read mode flag for open_reel dirloc: ds byte ;directory flag in rename, etc. seqio: ds byte ;1 if sequential i/o @@ -2954,7 +2928,7 @@ dminx: ds byte ;local for diskwrite searchl:ds byte ;search length searcha:ds word ;search address tinfo: ds word ;temp for info in "make" -single: ds byte ;set true if single byte allocation map +single: ds byte ;EQU true if single byte allocation map resel: ds byte ;reselection flag olddsk: ds byte ;disk on entry to bdos fcbdsk: ds byte ;disk named in fcb @@ -2969,5 +2943,8 @@ dptr: ds byte ;directory pointer 0,1,2,3 dcnt: ds word ;directory counter 0,1,...,dirmax drec: ds word ;directory record 0,1,...,dirmax/4 -bios equ ($ & 0ff00h)+100h ;next module +bios equ 0C000h;next module end + + + diff --git a/bdos.sym b/bdos.sym new file mode 100644 index 0000000..bb9d68a --- /dev/null +++ b/bdos.sym @@ -0,0 +1,386 @@ +tinfo: EQU 0x0000EDED +setusrcode: EQU 0x0000ED4D +sthl_ret: EQU 0x0000ED3B +qselect: EQU 0x0000ECD4 +olddsk: EQU 0x0000EDF1 +noselect: EQU 0x0000EC87 +reselect: EQU 0x0000EC63 +curselect: EQU 0x0000EC57 +dlog: EQU 0x0000EDC1 +select: EQU 0x0000EC32 +setrandom: EQU 0x0000EC1F +getnextsize: EQU 0x0000EC17 +setsize: EQU 0x0000EC1D +getsize: EQU 0x0000EBF5 +getfilesize: EQU 0x0000EBE3 +compute_rr: EQU 0x0000EBB6 +randiskwrite: EQU 0x0000EBAD +randiskread: EQU 0x0000EBA4 +badseek: EQU 0x0000EB95 +seekok: EQU 0x0000EB90 +ranclose: EQU 0x0000EB58 +seekerr: EQU 0x0000EB9C +rseek1: EQU 0x0000EB12 +rseek: EQU 0x0000EB0E +nospace: EQU 0x0000EB09 +diskwr3: EQU 0x0000EB0B +diskwr2: EQU 0x0000EADD +fill1: EQU 0x0000EAA5 +fill0: EQU 0x0000EA97 +diskwr11: EQU 0x0000EAC6 +diskwru: EQU 0x0000EA77 +allocwd: EQU 0x0000EA6F +blockok: EQU 0x0000EA53 +nopblock: EQU 0x0000EA46 +dminx: EQU 0x0000EDE9 +diskwr1: EQU 0x0000EA79 +diskwr0: EQU 0x0000EA27 +diskwrite: EQU 0x0000EA0E +seqdiskwrite: EQU 0x0000EA09 +diskeof: EQU 0x0000EA06 +recordok: EQU 0x0000E9F1 +diskread: EQU 0x0000E9CC +seqdiskread: EQU 0x0000E9C7 +open_reel2: EQU 0x0000E9BA +rmf: EQU 0x0000EDE5 +open_r_err: EQU 0x0000E9C1 +open_reel1: EQU 0x0000E9B7 +open_reel0: EQU 0x0000E999 +open_mod: EQU 0x0000E98D +open_reel: EQU 0x0000E964 +make0: EQU 0x0000E950 +efcb: EQU 0x0000EDBE +make: EQU 0x0000E92E +fcb_copied: EQU 0x0000EDE4 +endmerge: EQU 0x0000E921 +dmset: EQU 0x0000E906 +mergerr: EQU 0x0000E929 +buffnzero: EQU 0x0000E8EA +fcbnzero: EQU 0x0000E8E4 +merged: EQU 0x0000E8F1 +merge0: EQU 0x0000E8D6 +close: EQU 0x0000E8AB +mergezero: EQU 0x0000E89D +open_rcnt: EQU 0x0000E894 +open_copy: EQU 0x0000E863 +open: EQU 0x0000E85A +indic0: EQU 0x0000E849 +indicators: EQU 0x0000E844 +rename0: EQU 0x0000E830 +rename: EQU 0x0000E81F +seek_copy: EQU 0x0000E819 +copy_dir: EQU 0x0000E80A +copy_fcb: EQU 0x0000E806 +retblock0: EQU 0x0000E7FD +retblock: EQU 0x0000E7F4 +righttst: EQU 0x0000E7D8 +lefttst: EQU 0x0000E7C6 +get_block: EQU 0x0000E7C4 +delete0: EQU 0x0000E7AA +delete: EQU 0x0000E7A2 +searchext: EQU 0x0000E778 +searchok: EQU 0x0000E781 +endsearch: EQU 0x0000E788 +searchloop: EQU 0x0000E758 +searchnext: EQU 0x0000E74F +search_fin: EQU 0x0000E79A +searchn: EQU 0x0000E732 +searcha: EQU 0x0000EDEB +searchl: EQU 0x0000EDEA +search: EQU 0x0000E71D +compext: EQU 0x0000E70C +dirloc: EQU 0x0000EDE6 +copy_dirloc: EQU 0x0000E706 +initial2: EQU 0x0000E6D7 +dirblk: EQU 0x0000EDDC +initial0: EQU 0x0000E6B6 +initialize: EQU 0x0000E6A8 +scanm3: EQU 0x0000E6A2 +scandm2: EQU 0x0000E693 +scandm1: EQU 0x0000E68D +scandm0: EQU 0x0000E67A +scandm: EQU 0x0000E670 +rotr: EQU 0x0000E669 +set_alloc_bit: EQU 0x0000E661 +rotl: EQU 0x0000E65B +alloca: EQU 0x0000EDD1 +getallocbit: EQU 0x0000E63A +read_dir1: EQU 0x0000E625 +read_dir0: EQU 0x0000E61E +read_dir: EQU 0x0000E60A +set_end_dir: EQU 0x0000E603 +end_of_dir: EQU 0x0000E5FA +dir_to_user: EQU 0x0000E5EE +setdma: EQU 0x0000E5E8 +dmaad: EQU 0x0000EDC3 +rd_dir: EQU 0x0000E5D9 +setdata: EQU 0x0000E5DF +setdir: EQU 0x0000E5E5 +wrdir: EQU 0x0000E5CB +initial_cs: EQU 0x0000E5C9 +checka: EQU 0x0000EDCF +chksiz: EQU 0x0000EDDE +checksum: EQU 0x0000E5A3 +newchecksum: EQU 0x0000E5A1 +subdh: EQU 0x0000E59A +setcdr: EQU 0x0000E591 +compcdr: EQU 0x0000E584 +setfwf: EQU 0x0000E57D +clrmodnum: EQU 0x0000E577 +getmodnum: EQU 0x0000E56E +addh: EQU 0x0000E569 +dptr: EQU 0x0000EDFB +pdollar: EQU 0x0000E6FB +check_write: EQU 0x0000E559 +check_rofile: EQU 0x0000E54B +getdptra: EQU 0x0000E563 +check_rodir: EQU 0x0000E548 +dirmax: EQU 0x0000EDDA +set_ro: EQU 0x0000E530 +rodsk: EQU 0x0000EDBF +nowrite: EQU 0x0000E522 +set_cdisk: EQU 0x0000E50F +hlrotl0: EQU 0x0000E509 +hlrotl: EQU 0x0000E508 +computecs0: EQU 0x0000E501 +compute_cs: EQU 0x0000E4FB +hlrotr0: EQU 0x0000E4ED +setfcb1: EQU 0x0000E4E0 +seqio: EQU 0x0000EDE7 +setfcb: EQU 0x0000E4D4 +extmsk: EQU 0x0000EDD7 +rcount: EQU 0x0000EDF3 +getfcb: EQU 0x0000E4BD +getfcba: EQU 0x0000E4B0 +getexta: EQU 0x0000E4A8 +blkmsk: EQU 0x0000EDD6 +arecord1: EQU 0x0000EDF9 +atran0: EQU 0x0000E492 +atran: EQU 0x0000E48C +allocated: EQU 0x0000E486 +index: EQU 0x0000E479 +getdmd: EQU 0x0000E473 +getdm: EQU 0x0000E460 +dmpos2: EQU 0x0000E45E +dmpos1: EQU 0x0000E454 +extval: EQU 0x0000EDF4 +dmpos0: EQU 0x0000E445 +vrecord: EQU 0x0000EDF5 +blkshf: EQU 0x0000EDD5 +dm_position: EQU 0x0000E43E +invis: EQU 0x0000000A +rofile: EQU 0x00000009 +ranrec: EQU 0x00000021 +nxtrec: EQU 0x00000020 +lstfcb: EQU 0x0000001F +dskmap: EQU 0x00000010 +reccnt: EQU 0x0000000F +namlen: EQU 0x0000000F +fwfmsk: EQU 0x00000080 +maxmod: EQU 0x0000000F +modnum: EQU 0x0000000E +ubytes: EQU 0x0000000D +maxext: EQU 0x0000001F +extnum: EQU 0x0000000C +fcbshf: EQU 0x00000005 +dskmsk: EQU 0x00000003 +dirrec: EQU 0x00000004 +fcblen: EQU 0x00000020 +recsiz: EQU 0x00000080 +lstrec: EQU 0x0000007F +empty: EQU 0x000000E5 +offset: EQU 0x0000EDE0 +seek2: EQU 0x0000E40F +seek1: EQU 0x0000E3FA +seek0: EQU 0x0000E3E4 +seek: EQU 0x0000E3D1 +drec: EQU 0x0000EDFE +arecord: EQU 0x0000EDF7 +hlrotr: EQU 0x0000E4EC +dskshf: EQU 0x00000002 +dcnt: EQU 0x0000EDFC +seek_dir: EQU 0x0000E3C3 +wrbuff: EQU 0x0000E3B8 +diocomp: EQU 0x0000E3BB +rdbuff: EQU 0x0000E3B2 +home: EQU 0x0000E3A1 +retselect: EQU 0x0000E39D +single: EQU 0x0000EDEF +maxall: EQU 0x0000EDD8 +dpblist: EQU 0x0000000F +sectpt: EQU 0x0000EDD3 +dpbaddr: EQU 0x0000EDCD +addlist: EQU 0x00000008 +buffa: EQU 0x0000EDCB +tranv: EQU 0x0000EDE2 +curreca: EQU 0x0000EDC9 +curtrka: EQU 0x0000EDC7 +cdrmaxa: EQU 0x0000EDC5 +selectdisk: EQU 0x0000E359 +move0: EQU 0x0000E350 +move: EQU 0x0000E34F +goerr: EQU 0x0000E34A +sel_error: EQU 0x0000E347 +noupdate: EQU 0x0000EAEA +tbuff: EQU 0x00000080 +tfcb: EQU 0x0000005C +word: EQU 0x00000002 +byte: EQU 0x00000001 +enddir: EQU 0x0000FFFF +_false: EQU 0x00000000 +_true: EQU 0x000000FF +dvers: EQU 0x00000022 +lret: EQU 0x0000E345 +usrcode: EQU 0x0000E341 +setlret1: EQU 0x0000E305 +func_ret: EQU 0x0000E304 +retmon: EQU 0x0000EDA3 +dirinp: EQU 0x0000E2E0 +sta_ret: EQU 0x0000E301 +notc: EQU 0x0000E2BD +rdecho: EQU 0x0000E2A6 +backsp: EQU 0x0000E299 +rep1: EQU 0x0000E28A +rep0: EQU 0x0000E278 +notr: EQU 0x0000E2A6 +notu: EQU 0x0000E26B +backx: EQU 0x0000E24E +notx: EQU 0x0000E25F +notp: EQU 0x0000E248 +note: EQU 0x0000E237 +rdech1: EQU 0x0000E2A9 +notrub: EQU 0x0000E226 +linelen: EQU 0x0000E270 +noth: EQU 0x0000E216 +readen: EQU 0x0000E2C1 +readn0: EQU 0x0000E1F1 +readnx: EQU 0x0000E1EF +read: EQU 0x0000E1E1 +strtcol: EQU 0x0000E30B +crlfp0: EQU 0x0000E1B9 +crlfp: EQU 0x0000E1B1 +pctlh: EQU 0x0000E1AC +backup: EQU 0x0000E1A4 +tab0: EQU 0x0000E196 +ctlout: EQU 0x0000E17F +notbacksp: EQU 0x0000E179 +column: EQU 0x0000E30C +listcp: EQU 0x0000E30D +compout: EQU 0x0000E162 +compcol: EQU 0x0000E30A +conout: EQU 0x0000E148 +conb0: EQU 0x0000E142 +conb1: EQU 0x0000E145 +conbrk: EQU 0x0000E123 +tabout: EQU 0x0000E190 +echoc: EQU 0x0000E114 +conech: EQU 0x0000E106 +kbchar: EQU 0x0000E30E +conin: EQU 0x0000E0FB +print: EQU 0x0000E1D3 +curdsk: EQU 0x0000E342 +crlf: EQU 0x0000E1C9 +dskerr: EQU 0x0000E0C6 +dskmsg: EQU 0x0000E0BA +rofmsg: EQU 0x0000E0DC +rodmsg: EQU 0x0000E0E1 +wait_err: EQU 0x0000E0B4 +selmsg: EQU 0x0000E0D5 +errflg: EQU 0x0000E0E5 +permsg: EQU 0x0000E0CA +func40: EQU 0x0000EDAD +func39: EQU 0x0000E304 +func38: EQU 0x0000E304 +func37: EQU 0x0000ED65 +func36: EQU 0x0000EC1F +func35: EQU 0x0000ED5F +func34: EQU 0x0000ED59 +func33: EQU 0x0000ED53 +func32: EQU 0x0000ED3F +func31: EQU 0x0000ED38 +func30: EQU 0x0000ED2F +func29: EQU 0x0000ED29 +func28: EQU 0x0000E530 +func27: EQU 0x0000ED23 +func26: EQU 0x0000ED1C +func25: EQU 0x0000ED16 +func24: EQU 0x0000ED10 +func23: EQU 0x0000ED07 +func22: EQU 0x0000ECFE +func21: EQU 0x0000ECF8 +func20: EQU 0x0000ECF2 +func19: EQU 0x0000ECE9 +func18: EQU 0x0000ECDA +func17: EQU 0x0000ECBD +func16: EQU 0x0000ECB7 +func15: EQU 0x0000ECAE +func14: EQU 0x0000EC57 +func13: EQU 0x0000EC95 +func12: EQU 0x0000EC90 +diskf: EQU 0x0000000C +func11: EQU 0x0000E2FE +func10: EQU 0x0000E1E1 +func9: EQU 0x0000E2F8 +func8: EQU 0x0000E2F3 +func7: EQU 0x0000E2ED +func6: EQU 0x0000E2D4 +func3: EQU 0x0000E2CE +func2: EQU 0x0000E190 +func1: EQU 0x0000E2C8 +functab: EQU 0x0000E047 +nfuncs: EQU 0x00000029 +goback: EQU 0x0000ED86 +resel: EQU 0x0000EDF0 +fcbdsk: EQU 0x0000EDF2 +lstack: EQU 0x0000E341 +entsp: EQU 0x0000E30F +aret: EQU 0x0000E345 +linfo: EQU 0x0000EDE8 +info: EQU 0x0000E343 +rofsub: EQU 0x0000E0B1 +roferr: EQU 0x0000E00F +rodsub: EQU 0x0000E0AB +roderr: EQU 0x0000E00D +selsub: EQU 0x0000E0A5 +selerr: EQU 0x0000E00B +persub: EQU 0x0000E099 +pererr: EQU 0x0000E009 +bdose: EQU 0x0000E011 +ctl: EQU 0x0000005E +lf: EQU 0x0000000A +cr: EQU 0x0000000D +tab: EQU 0x00000009 +rubout: EQU 0x0000007F +ctlz: EQU 0x0000001A +ctlx: EQU 0x00000018 +ctlu: EQU 0x00000015 +ctls: EQU 0x00000013 +ctlr: EQU 0x00000012 +ctlp: EQU 0x00000010 +ctlh: EQU 0x00000008 +ctle: EQU 0x00000005 +ctlc: EQU 0x00000003 +sectran: EQU 0x0000EF30 +liststf: EQU 0x0000EF2D +writef: EQU 0x0000EF2A +readf: EQU 0x0000EF27 +setdmaf: EQU 0x0000EF24 +setsecf: EQU 0x0000EF21 +settrkf: EQU 0x0000EF1E +seldskf: EQU 0x0000EF1B +homef: EQU 0x0000EF18 +readerf: EQU 0x0000EF15 +punchf: EQU 0x0000EF12 +listf: EQU 0x0000EF0F +conoutf: EQU 0x0000EF0C +coninf: EQU 0x0000EF09 +constf: EQU 0x0000EF06 +wbootf: EQU 0x0000EF03 +bootf: EQU 0x0000EF00 +bios: EQU 0x0000EF00 +bdosa: EQU 0x00000006 +ioloc: EQU 0x00000003 +reboot: EQU 0x00000000 +ssize: EQU 0x00000018 +BDOS_ORG: EQU 0x0000E000 +patch1: EQU 0x00000001 diff --git a/bios.asm b/bios.asm new file mode 100644 index 0000000..b392a4d --- /dev/null +++ b/bios.asm @@ -0,0 +1,158 @@ +; Minimal CP/M 2.2 BIOS for the emulator +; +; Provides console I/O via port 0 (mapped to the GUI terminal), +; stubs disk routines, and jumps to the CCP on warm boot. + +BDOS_ADDR equ 0E000h +CCP_START equ 0EC5Ch ; from ccp.lst + + org 0F200h + +; Jump table (standard CP/M order) + jp boot + jp wboot + jp const + jp conin + jp conout + jp list + jp punch + jp reader + jp home + jp seldsk + jp settrk + jp setsec + jp setdma + jp read + jp write + jp listst + jp sectran + +; ------------------------------------------------------------ +; Console I/O +; ------------------------------------------------------------ +boot: + ; set JMP vectors at 0000h and 0005h + ld a,0C3h ; JMP opcode + ld (0000h),a + ld hl,wboot + ld (0001h),hl + ld (0005h),a + ld hl,BDOS_ADDR + ld (0006h),hl + ; defaults + ld hl,0080h + ld (dmaaddr),hl + ld a,0FFh + ld (kbbuf),a + ; fall through to warm boot +wboot: + ld sp,0F800h ; place stack high + ld c,0 ; default drive/user in C for CCP + jp CCP_START + +const: + ld a,(kbbuf) + cp 0FFh + jr nz,_const_ready + in a,(0) ; pull from terminal; 0 means none + cp 0 + jr z,_const_empty + ld (kbbuf),a +_const_ready: + or a ; Z if none, NZ if ready + ret +_const_empty: + xor a + ret + +conin: + ld a,(kbbuf) + cp 0FFh + jr nz,_con_use_buf +_con_read: + in a,(0) + cp 0 + jr z,_con_read + jp _con_done_port +_con_use_buf: + ; A already holds buffered char +_con_done_port: + ld b,a ; save char + ld a,0FFh + ld (kbbuf),a ; buffer now empty + ld a,b + ret + +conout: + ld a,c + out (0),a + ret + +list: +punch: +reader: + xor a ; no devices + ret + +; ------------------------------------------------------------ +; Disk stubs / bookkeeping +; ------------------------------------------------------------ +home: + ld hl,0 + ld (curtrk),hl + ret + +seldsk: + ; drive in C, return HL -> dpb (always drive 0) + ld a,c + and 0Fh + ld (curdrv),a + ld hl,dpb + ret + +settrk: + ld (curtrk),hl + ret + +setsec: + ld (cursec),hl + ret + +setdma: + ld (dmaaddr),hl + ret + +read: +write: + xor a ; 0 => OK + ret + +listst: + xor a + ret + +sectran: + ; no translation; HL already logical sector + ret + +; ------------------------------------------------------------ +; Data +; ------------------------------------------------------------ +curtrk: dw 0 +cursec: dw 0 +curdrv: db 0 +dmaaddr:dw 0080h +kbbuf: db 0FFh + +; Simple DPB (placeholder, not used by stubs) +dpb: + dw 32 ; spt + db 3 ; bsh (1K blocks) + db 7 ; blm + db 0 ; exm + dw 242 ; dsm + dw 63 ; drm + db 080h ; al0 + db 000h ; al1 + dw 0 ; cks + dw 2 ; off diff --git a/bios.sym b/bios.sym new file mode 100644 index 0000000..0fff10b --- /dev/null +++ b/bios.sym @@ -0,0 +1,30 @@ +cursec: EQU 0x0000F2B0 +dpb: EQU 0x0000F2B6 +curdrv: EQU 0x0000F2B2 +curtrk: EQU 0x0000F2AE +_con_done_port: EQU 0x0000F27E +_con_read: EQU 0x0000F275 +_con_use_buf: EQU 0x0000F27E +_const_empty: EQU 0x0000F26C +_const_ready: EQU 0x0000F26A +kbbuf: EQU 0x0000F2B5 +dmaaddr: EQU 0x0000F2B3 +sectran: EQU 0x0000F2AD +listst: EQU 0x0000F2AB +write: EQU 0x0000F2A9 +read: EQU 0x0000F2A9 +setdma: EQU 0x0000F2A5 +setsec: EQU 0x0000F2A1 +settrk: EQU 0x0000F29D +seldsk: EQU 0x0000F293 +home: EQU 0x0000F28C +reader: EQU 0x0000F28A +punch: EQU 0x0000F28A +list: EQU 0x0000F28A +conout: EQU 0x0000F286 +conin: EQU 0x0000F26E +const: EQU 0x0000F25A +wboot: EQU 0x0000F252 +boot: EQU 0x0000F233 +CCP_START: EQU 0x0000EC5C +BDOS_ADDR: EQU 0x0000E000 diff --git a/ccp.asm b/ccp.asm index 2f1ae7d..3222370 100644 --- a/ccp.asm +++ b/ccp.asm @@ -1,54 +1,57 @@ ; Reformatted and converted for cross-assembly by Macro Assembler AS ; Eric Smith 2018-01-24 -; from original source os2ccp.asm from -; http://www.cpm.z80.de/download/cpm2-plm.zip - -; Changes: -; multiple instructions per line split to separate lines -; dollar sign in labels replaced by underscore -; dollar sign (as digit separator) in binary constants removed -; single quotes around strings replaced with double quotes -; true and false replaced with _true and _false -; replaced "not" operator with "~" -; removed empty comments -; added ifdef origin to allow origin to be specified from command line -; added commments about serial number -; added ifdefs on "noserial" to omit serialization check - - - .cpu 8080 - - title "console command processor (CCP), ver 2.0" -; assembly language version of the CP/M console command processor - -; version 2.2 February, 1980 - -; Copyright (c) 1976, 1977, 1978, 1979, 1980 -; Digital Research -; Box 579, Pacific Grove, -; California, 93950 +; --- Clean modern CCP header for fixed CP/M memory map --- +; This version removes Digital Research’s origin/BDOS auto-calculation. +; CCP and BDOS locations must be provided explicitly. +; +; Captain’s layout: +; BDOS = 0E000h +; CCP = 0E900h +; +; You may override these from the command line: +; sjasmplus --define=CCP_ORG=0xE900 --define=BDOS_ORG=0xE000 ccp.asm +; ------------------------------------------------------------ + +; .cpu 8080 + +; title "console command processor (CCP), ver 2.0" +; CPU 8080 _false equ 0000h _true equ ~_false -testing equ _false ;true if debugging - - - ifdef origin - org origin -bdosl equ $+800h ;bdos location - else - if testing - org 3400h -bdosl equ $+800h ;bdos location - else - org 000h -bdosl equ $+800h ;bdos location +testing equ _false ; debugging disabled + +; ------------------------------------------------------------ +; Explicit CP/M memory layout +; ------------------------------------------------------------ +; If caller does not define CCP_ORG or BDOS_ORG, use defaults. +; These match the Captain's architecture: +; CCP: 0xE900 +; BDOS: 0xE000 +; ------------------------------------------------------------ + + ifndef CCP_ORG +CCP_ORG equ 0E900h endif + + ifndef BDOS_ORG +BDOS_ORG equ 0E000h endif + +; CCP starts here + org CCP_ORG + +; Explicit BDOS entry address, never computed relative to CCP +bdosl equ BDOS_ORG + +; ------------------------------------------------------------ +; Remaining legacy symbols retained intact +; ------------------------------------------------------------ tran equ 100h tranm equ $ ccploc equ $ + ; ******************************************************** ; * Base of CCP contains the following code/data * ; * ccp: jmp ccpstart (start with command) * @@ -69,8 +72,8 @@ ccploc equ $ ; * ables the automatic command execution. * ; ******************************************************** - jmp ccpstart ;start ccp with possible initial command - jmp ccpclear ;clear the command buffer + jp ccpstart ;start ccp with possible initial command + jp ccpclear ;clear the command buffer maxlen: db 127 ;max buffer length comlen: db 0 ;command length (filled in by dos) ; (command executed initially if comlen non zero) @@ -122,278 +125,278 @@ eofile equ 1ah ;end of file ; utility procedures printchar: - mov e,a - mvi c,pcharf - jmp bdos + ld e,a + ld c,pcharf + jp bdos printbc: ;print character, but save b,c registers - push b + push bc call printchar - pop b + pop bc ret crlf: - mvi a,cr + ld a,cr call printbc - mvi a,lf - jmp printbc + ld a,lf + jp printbc blank: - mvi a,' ' - jmp printbc + ld a,' ' + jp printbc print: ;print string starting at b,c until next 00 entry - push b ;now print the string + push bc ;now print the string call crlf - pop h -prin0: mov a,m ;stop on 00 - ora a - rz - inx h ;ready for next - push h + pop hl +prin0: ld a,(hl) ;stop on 00 + or a + ret z + inc hl ;ready for next + push hl call printchar ;character printed - pop h - jmp prin0 ;for another character + pop hl + jp prin0 ;for another character initialize: - mvi c,initf - jmp bdos + ld c,initf + jp bdos select: - mov e,a - mvi c,self - jmp bdos + ld e,a + ld c,self + jp bdos bdos_inr: call bdos - sta dcnt - inr a + ld (dcnt),a + inc a ret open: ;open the file given by d,e - mvi c,openf - jmp bdos_inr + ld c,openf + jp bdos_inr openc: ;open comfcb - xra a ;clear next record to read - sta comrec - lxi d,comfcb - jmp open + xor a ;clear next record to read + ld (comrec),a + ld de,comfcb + jp open close: ;close the file given by d,e - mvi c,closef - jmp bdos_inr + ld c,closef + jp bdos_inr search: ;search for the file given by d,e - mvi c,searf - jmp bdos_inr + ld c,searf + jp bdos_inr searchn: ;search for the next occurrence of the file given by d,e - mvi c,searnf - jmp bdos_inr + ld c,searnf + jp bdos_inr searchcom: ;search for comfcb file - lxi d,comfcb - jmp search + ld de,comfcb + jp search delete: ;delete the file given by d,e - mvi c,delf - jmp bdos + ld c,delf + jp bdos bdos_cond: call bdos - ora a + or a ret diskread: ;read the next record from the file given by d,e - mvi c,dreadf - jmp bdos_cond + ld c,dreadf + jp bdos_cond diskreadc: ;read the comfcb file - lxi d,comfcb - jmp diskread + ld de,comfcb + jp diskread diskwrite: ;write the next record to the file given by d,e - mvi c,dwritf - jmp bdos_cond + ld c,dwritf + jp bdos_cond make: ;create the file given by d,e - mvi c,makef - jmp bdos_inr + ld c,makef + jp bdos_inr renam: ;rename the file given by d,e - mvi c,renf - jmp bdos + ld c,renf + jp bdos getuser: ;return current user code in a - mvi e,0ffh ;drop through to setuser + ld e,0ffh ;drop through to setuser setuser: - mvi c,userf ;sets user number - jmp bdos + ld c,userf ;sets user number + jp bdos saveuser: ;save user#/disk# before possible ^c or transient call getuser ;code to a - add a ;rot left - add a - add a - add a - lxi h,cdisk ;4b=user, 4b=disk - ora m - sta diska ;stored away in memory for later + add a,a ;rot left + add a,a + add a,a + add a,a + ld hl,cdisk ;4b=user, 4b=disk + or (hl) + ld (diska),a ;stored away in memory for later ret setdiska: - lda cdisk ;user/disk - sta diska + ld a,(cdisk) ;user/disk + ld (diska),a ret translate: ;translate character in register A to upper case - cpi 61h ;return if below lower case a - rc - cpi 7bh ;return if above lower case z - rnc - ani 5fh ;translated to upper case + cp 61h ;return if below lower case a + ret c + cp 7bh ;return if above lower case z + ret nc + and 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 + ld a,(submit) + or a + jp z,nosub ;scanning a submit file ;change drives to open and read the file - lda cdisk - ora a - mvi a,0 - cnz select + ld a,(cdisk) + or a + ld a,0 + call nz,select ;have to open again in case xsub present - lxi d,subfcb ;skip if no sub + ld de,subfcb ;skip if no sub call open - jz nosub - lda subrc ;read last record(s) first - dcr a - sta subcr ;current record to read - lxi d,subfcb ;end of file if last record + jp z,nosub + ld a,(subrc) ;read last record(s) first + dec a + ld (subcr),a ;current record to read + ld de,subfcb ;end of file if last record call diskread - jnz nosub + jp nz,nosub ;disk read is ok, transfer to combuf - lxi d,comlen - lxi h,buff - mvi b,128 + ld de,comlen + ld hl,buff + ld b,128 call move0 ;line is transferred, close the file with a ;deleted record - lxi h,submod ;clear fwflag - mvi m,0 - inx h ;one less record - dcr m - lxi d,subfcb + ld hl,submod ;clear fwflag + ld (hl),0 + inc hl ;one less record + dec (hl) + ld de,subfcb call close - jz nosub + jp z,nosub ;close went ok, return to original drive - lda cdisk - ora a - cnz select + ld a,(cdisk) + or a + call nz,select ;print to the 00 - lxi h,combuf + ld hl,combuf call prin0 call break_key - jz noread + jp z,noread call del_sub ;break key depressed - jmp ccp + jp ccp nosub: ;no submit file call del_sub ;translate to upper case, store zero at end call saveuser ;user # save in case control c - mvi c,rbuff - lxi d,maxlen + ld c,rbuff + ld de,maxlen call bdos call setdiska ;no control c, so restore diska noread: ;enter here from submit file ;set the last character to zero for later scans - lxi h,comlen ;length is in b - mov b,m + ld hl,comlen ;length is in b + ld b,(hl) readcom0: - inx h ;end of scan? - mov a,b - ora a - jz readcom1 ;get character and translate - mov a,m + inc hl ;end of scan? + ld a,b + or a + jp z,readcom1 ;get character and translate + ld a,(hl) call translate - mov m,a - dcr b - jmp readcom0 + ld (hl),a + dec b + jp readcom0 readcom1: ;end of scan, h,l address end of command - mov m,a ;store a zero - lxi h,combuf ;ready to scan to zero - shld comaddr + ld (hl),a ;store a zero + ld hl,combuf ;ready to scan to zero + ld (comaddr),hl ret break_key: ;check for a character ready at the console - mvi c,breakf + ld c,breakf call bdos - ora a - rz - mvi c,rcharf ;character cleared + or a + ret z + ld c,rcharf ;character cleared call bdos - ora a + or a ret cselect: ;get the currently selected drive number to reg-A - mvi c,cself - jmp bdos + ld c,cself + jp bdos setdmabuff: ;set default buffer dma address - lxi d,buff ;(drop through) + ld de,buff ;(drop through) setdma: ;set dma address to d,e - mvi c,dmaf - jmp bdos + ld c,dmaf + jp bdos del_sub: ;delete the submit file, and set submit flag to false - lxi h,submit ;return if no sub file - mov a,m - ora a - rz - mvi m,0 ;submit flag is set to false - xra a ;on drive a to erase file + ld hl,submit ;return if no sub file + ld a,(hl) + or a + ret z + ld (hl),0 ;submit flag is set to false + xor a ;on drive a to erase file call select - lxi d,subfcb + ld de,subfcb call delete - lda cdisk ;back to original drive - jmp select + ld a,(cdisk) ;back to original drive + jp select ifndef noserial serialize: ;check serialization - lxi d,serial ;check six bytes - lxi h,bdosl - mvi b,6 -ser0: ldax d - cmp m - jnz badserial - inx d - inx h - dcr b - jnz ser0 + ld de,serial ;check six bytes + ld hl,bdosl + ld b,6 +ser0: ld a,(de) + cp (hl) + jp nz,badserial + inc de + inc hl + dec b + jp nz,ser0 ret ;serial number is ok endif @@ -401,198 +404,198 @@ comerr: ;error in command string starting at position ;'staddr' and ending with first delimiter call crlf ;space to next line - lhld staddr ;h,l address first to print + ld hl,(staddr) ;h,l address first to print comerr0: ;print characters until blank or zero - mov a,m ; not blank - cpi ' ' - jz comerr1 - ora a ; not zero, so print it - jz comerr1 - push h + ld a,(hl) ; not blank + cp ' ' + jp z,comerr1 + or a ; not zero, so print it + jp z,comerr1 + push hl call printchar - pop h - inx h - jmp comerr0; for another character + pop hl + inc hl + jp comerr0 ; for another character comerr1: ;print question mark,and delete sub file - mvi a,'?' + ld a,'?' call printchar call crlf call del_sub - jmp ccp ;restart with next command + 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 - ldax d ;not the last element - ora a - rz - cpi ' ' ;non graphic - jc comerr - rz ;treat blank as delimiter - cpi '=' - rz - cpi la ;left arrow - rz - cpi '.' - rz - cpi ':' - rz - cpi ';' - rz - cpi '<' - rz - cpi '>' - rz + ld a,(de) ;not the last element + or a + ret z + cp ' ' ;non graphic + jp c,comerr + ret z ;treat blank as delimiter + cp '=' + ret z + cp la ;left arrow + ret z + cp '.' + ret z + cp ':' + ret z + cp ';' + ret z + cp '<' + ret z + cp '>' + ret z ret ;delimiter not found deblank: ;deblank the input line - ldax d ;treat end of line as blank - ora a - rz - cpi ' ' - rnz - inx d - jmp deblank + ld a,(de) ;treat end of line as blank + or a + ret z + cp ' ' + ret nz + inc de + jp deblank addh: ;add a to h,l - add l - mov l,a - rnc - inr h + add a,l + ld l,a + ret nc + inc h ret fillfcb0: ;equivalent to fillfcb(0) - mvi a,0 + ld a,0 fillfcb: - lxi h,comfcb ;fcb rescanned at end + ld hl,comfcb ;fcb rescanned at end call addh - push h - push h - xra a ;clear selected disk (in case A:...) - sta sdisk - lhld comaddr ;command address in d,e - xchg + push hl + push hl + xor a ;clear selected disk (in case A:...) + ld (sdisk),a + ld hl,(comaddr) ;command address in d,e + ex de,hl call deblank ;to first non-blank character - xchg ;in case of errors - shld staddr - xchg ;d,e has command, h,l has fcb address - pop h + ex de,hl ;in case of errors + ld (staddr),hl + ex de,hl ;d,e has command, h,l has fcb address + pop hl ;look for preceding file name A: B: ... - ldax d ;use current disk if empty command - ora a - jz setcur0 - sbi 'A'-1 ;disk name held in b if : follows - mov b,a - inx d ;set disk name if : - ldax d - cpi ':' - jz setdsk + ld a,(de) ;use current disk if empty command + or a + jp z,setcur0 + sbc a,'A'-1 ;disk name held in b if : follows + ld b,a + inc de ;set disk name if : + ld a,(de) + cp ':' + jp z,setdsk setcur: ;set current disk - dcx d ;back to first character of command + dec de ;back to first character of command setcur0: - lda cdisk - mov m,a - jmp setname + ld a,(cdisk) + ld (hl),a + jp setname setdsk: ;set disk to name in register b - mov a,b ;mark as disk selected - sta sdisk - mov m,b ;past the : - inx d + ld a,b ;mark as disk selected + ld (sdisk),a + ld (hl),b ;past the : + inc de setname: ;set the file name field - mvi b,8 ;file name length (max) + ld b,8 ;file name length (max) setnam0: call delim ;not a delimiter - jz padname - inx h ;must be ?'s - cpi '*' - jnz setnam1 - mvi m,'?' ;to dec count - jmp setnam2 + jp z,padname + inc hl ;must be ?'s + cp '*' + jp nz,setnam1 + ld (hl),'?' ;to dec count + jp setnam2 setnam1: - mov m,a ;store character to fcb - inx d + ld (hl),a ;store character to fcb + inc de setnam2: - dcr b ;count down length - jnz setnam0 + dec b ;count down length + jp nz,setnam0 ;end of name, truncate remainder trname: call delim ;set type field if delimiter - jz setty - inx d - jmp trname + jp z,setty + inc de + jp trname padname: - inx h - mvi m,' ' - dcr b - jnz padname + inc hl + ld (hl),' ' + dec b + jp nz,padname setty: ;set the type field - mvi b,3 ;skip the type field if no . - cpi '.' - jnz padty - inx d ;past the ., to the file type field + ld b,3 ;skip the type field if no . + cp '.' + jp nz,padty + inc de ;past the ., to the file type field setty0: ;set the field from the command buffer call delim - jz padty - inx h - cpi '*' - jnz setty1 - mvi m,'?' ;since * specified - jmp setty2 + jp z,padty + inc hl + cp '*' + jp nz,setty1 + ld (hl),'?' ;since * specified + jp setty2 setty1: ;not a *, so copy to type field - mov m,a - inx d + ld (hl),a + inc de setty2: ;decrement count and go again - dcr b - jnz setty0 + dec b + jp nz,setty0 ;end of type field, truncate trtyp: ;truncate type field call delim - jz efill - inx d - jmp trtyp + jp z,efill + inc de + jp trtyp padty: ;pad the type field with blanks - inx h - mvi m,' ' - dcr b - jnz padty + inc hl + ld (hl),' ' + dec b + jp nz,padty efill: ;end of the 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 ;set new starting point - shld comaddr + ld b,3 +efill0: inc hl + ld (hl),0 + dec b + jp nz,efill0 + ex de,hl ;set new starting point + ld (comaddr),hl ;recover the start address of the fcb and count ?'s - pop h ;b=0, c=8+3 - lxi b,11 -scnq: inx h - mov a,m - cpi '?' - jnz scnq0 + pop hl ;b=0, c=8+3 + ld bc,11 +scnq: inc hl + ld a,(hl) + cp '?' + jp nz,scnq0 ;? found, count it in b - inr b -scnq0: dcr c - jnz scnq + inc b +scnq0: dec c + jp nz,scnq ;number of ?'s in c, move to a and return with flags set - mov a,b - ora a + ld a,b + or a ret intvec: @@ -614,104 +617,104 @@ serial: db 0 ; OEM number, low byte intrinsic: ;look for intrinsic functions (comfcb has been filled) - lxi h,intvec ;c counts intrinsics as scanned - mvi c,0 + ld hl,intvec ;c counts intrinsics as scanned + ld c,0 intrin0: - mov a,c ;done with scan? - cpi intlen - rnc + ld a,c ;done with scan? + cp intlen + ret nc ;no, more to scan - lxi d,comfcb+1 ;beginning of name - mvi b,4 ;length of match is in b + ld de,comfcb+1 ;beginning of name + ld b,4 ;length of match is in b intrin1: - ldax d ;match? - cmp m - jnz intrin2 ;skip if no match - inx d - inx h - dcr b - jnz intrin1 ;loop while matching + ld a,(de) ;match? + cp (hl) + jp nz,intrin2 ;skip if no match + inc de + inc hl + dec b + jp nz,intrin1 ;loop while matching ;complete match on name, check for blank in fcb - ldax d ;otherwise matched - cpi ' ' - jnz intrin3 - mov a,c ;with intrinsic number in a + ld a,(de) ;otherwise matched + cp ' ' + jp nz,intrin3 + ld a,c ;with intrinsic number in a ret intrin2: ;mismatch, move to end of intrinsic - inx h - dcr b - jnz intrin2 + inc hl + dec b + jp nz,intrin2 intrin3: ;try next intrinsic - inr c ;to next intrinsic number - jmp intrin0 ;for another round + inc c ;to next intrinsic number + jp intrin0 ;for another round ccpclear: ;clear the command buffer - xra a - sta comlen + xor a + ld (comlen),a ;drop through to start ccp ccpstart: ;enter here from boot loader - lxi sp,stack ;save initial disk number - push b + ld sp,stack ;save initial disk number + push bc ;(high order 4bits=user code, low 4bits=disk#) - mov a,c ;user code - rar - rar - rar - rar - ani 0fh + ld a,c ;user code + rr a + rr a + rr a + rr a + and 0fh - mov e,a ;user code selected + ld e,a ;user code selected call setuser ;initialize for this user, get $ flag call initialize ;0ffh in accum if $ file present - sta submit ;submit flag set if $ file present - pop b ;recall user code and disk number - mov a,c ;disk number in accumulator - ani 0fh - sta cdisk ;clears user code nibble + ld (submit),a ;submit flag set if $ file present + pop bc ;recall user code and disk number + ld a,c ;disk number in accumulator + and 0fh + ld (cdisk),a ;clears user code nibble call select ;proper disk is selected, now check sub files ;check for initial command - lda comlen ;assume typed already - ora a - jnz ccp0 + ld a,(comlen) ;assume typed already + or a + jp nz,ccp0 ccp: ;enter here on each command or error condition - lxi sp,stack + ld sp,stack call crlf ;print d> prompt, where d is disk name call cselect ;get current disk number - adi 'A' + add a,'A' call printchar - mvi a,'>' + ld a,'>' call printchar call readcom ;command buffer filled ccp0: ;(enter here from initialization with command full) - lxi d,buff ;default dma address at buff + ld de,buff ;default dma address at buff call setdma call cselect ;current disk number saved - sta cdisk + ld (cdisk),a call fillfcb0 ;command fcb filled - cnz comerr ;the name cannot be an ambiguous reference - lda sdisk - ora a - jnz userfunc + 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 - lxi h,jmptab ;index is in the accumulator - mov e,a ;index in d,e - mvi d,0 - dad d - dad d - mov a,m - inx h - mov h,m - mov l,a - pchl + ld hl,jmptab ;index is in the accumulator + ld e,a ;index in d,e + ld d,0 + add hl,de + add hl,de + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp (hl) ;pc changes to the proper intrinsic or user function jmptab: @@ -725,336 +728,336 @@ jmptab: ifndef noserial badserial: - LXI H,76F3H ;'DI HLT' instructions. + ld hl,76F3H ;'DI HLT' instructions. ;typo "lxi h,di or (hlt shl 8)" here originally, ;corrected by comparing to disassembly of Clark Calkins. - shld ccploc - lxi h,ccploc - pchl + ld (ccploc),hl + ld hl,ccploc + jp (hl) endif ;utility subroutines for intrinsic handlers readerr: ;print the read error message - lxi b,rdmsg - jmp print + ld bc,rdmsg + jp print rdmsg: db "READ ERROR",0 nofile: ;print no file message - lxi b,nofmsg - jmp print + ld bc,nofmsg + jp print nofmsg: db "NO FILE",0 getnumber: ;read a number from the command line call fillfcb0 ;should be number - lda sdisk ;cannot be prefixed - ora a - jnz comerr + ld a,(sdisk) ;cannot be prefixed + or a + jp nz,comerr ;convert the byte value in comfcb to binary - lxi h,comfcb+1 ;(b=0, c=11) - lxi b,11 + ld hl,comfcb+1 ;(b=0, c=11) + ld bc,11 ;value accumulated in b, c counts name length to zero -conv0: mov a,m - cpi ' ' - jz conv1 +conv0: ld a,(hl) + cp ' ' + jp z,conv1 ;more to scan, convert char to binary and add - inx h ;valid? - sui '0' - cpi 10 - jnc comerr - mov d,a ;save value - mov a,b ;mult by 10 - ani 11100000b - jnz comerr - mov a,b ;recover value - rlc ;*8 - rlc - rlc - add b - jc comerr - add b ;*8+*2 = *10 - jc comerr - add d ;+digit - jc comerr - mov b,a ;for another digit - dcr c - jnz conv0 + inc hl ;valid? + sub '0' + cp 10 + jp nc,comerr + ld d,a ;save value + ld a,b ;mult by 10 + and 11100000b + jp nz,comerr + ld a,b ;recover value + rlca ;*8 + rlca + rlca + add a,b + jp c,comerr + add a,b ;*8+*2 = *10 + jp c,comerr + add a,d ;+digit + jp c,comerr + ld b,a ;for another digit + dec c + jp nz,conv0 ret conv1: ;end of digits, check for all blanks - mov a,m ;blanks? - cpi ' ' - jnz comerr - inx h - dcr c - jnz conv1 - mov a,b ;recover value + ld a,(hl) ;blanks? + cp ' ' + jp nz,comerr + inc hl + dec c + jp nz,conv1 + ld 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 + ld b,3 +move0: ld a,(hl) + ld (de),a + inc hl + inc de + dec b + jp nz,move0 ret addhcf: ;buff + a + c to h,l followed by fetch - lxi h,buff - add c + ld hl,buff + add a,c call addh - mov a,m + ld a,(hl) ret setdisk: ;change disks for this command, if requested - xra a ;clear disk name from fcb - sta comfcb - lda sdisk ;no action if not specified - ora a - rz - dcr a ;already selected - lxi h,cdisk - cmp m - rz - jmp select + xor a ;clear disk name from fcb + ld (comfcb),a + ld a,(sdisk) ;no action if not specified + or a + ret z + dec a ;already selected + ld hl,cdisk + cp (hl) + ret z + jp select resetdisk: ;return to original disk after command - lda sdisk ;no action if not selected - ora a - rz - dcr a ;same disk - lxi h,cdisk - cmp m - rz - lda cdisk - jmp select + ld a,(sdisk) ;no action if not selected + or a + ret z + dec a ;same disk + ld hl,cdisk + cp (hl) + ret z + ld a,(cdisk) + jp select ;individual intrinsics follow direct: ;directory search call fillfcb0 ;comfcb gets file name call setdisk ;change disk drives if requested - lxi h,comfcb+1 ;may be empty request - mov a,m - cpi ' ' ;skip fill of ??? if not blank - jnz dir1 + ld hl,comfcb+1 ;may be empty request + ld a,(hl) + cp ' ' ;skip fill of ??? if not blank + jp nz,dir1 ;set comfcb to all ??? for current disk - mvi b,11 ;length of fill ????????.??? -dir0: mvi m,'?' - inx h - dcr b - jnz dir0 + ld b,11 ;length of fill ????????.??? +dir0: ld (hl),'?' + inc hl + dec b + jp nz,dir0 ;not a blank request, must be in comfcb -dir1: mvi e,0 ;E counts directory entries - push d +dir1: ld e,0 ;E counts directory entries + push de call searchcom ;first one has been found - cz nofile ;not found message -dir2: jz endir + call z,nofile ;not found message +dir2: jp z,endir ;found, but may be system file - lda dcnt ;get the location of the element - rrc - rrc - rrc - ani 1100000b - mov c,a + 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 - mvi a,sysfile ;value to A + ld a,sysfile ;value to A call addhcf - ral ;skip if system file - jc dir6 + rl a ;skip if system file + jp c,dir6 ;c holds index into buffer ;another fcb found, new line? - pop d - mov a,e - inr e - push d + pop de + ld a,e + inc e + push de ;e=0,1,2,3,...new line if mod 4 = 0 - ani 11b ;and save the test - push psw - jnz dirhdr0 ;header on current line + and 11b ;and save the test + push af + jp nz,dirhdr0 ;header on current line call crlf - push b + push bc call cselect - pop b + pop bc ;current disk in A - adi 'A' + add a,'A' call printbc - mvi a,':' + ld a,':' call printbc - jmp dirhdr1 ;skip current line hdr + jp dirhdr1 ;skip current line hdr dirhdr0: call blank ;after last one - mvi a,':' + ld 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 ;buff+a+c fetched + ld b,1 ;start with first character of name +dir3: ld a,b ;buff+a+c fetched call addhcf - ani 7fh ;mask flags + and 7fh ;mask flags ;may delete trailing blanks - cpi ' ' ;check for blank type - jnz dir4 - pop psw ;may be 3rd item - push psw - cpi 3 ;place blank at end if not - jnz dirb - mvi a,9 ;first char of type + cp ' ' ;check for blank type + jp nz,dir4 + pop af ;may be 3rd item + push af + cp 3 ;place blank at end if not + jp nz,dirb + ld a,9 ;first char of type call addhcf - ani 7fh - cpi ' ' - jz dir5 + and 7fh + cp ' ' + jp z,dir5 ;not a blank in the file type field -dirb: mvi a,' ' ;restore trailing filename chr +dirb: ld a,' ' ;restore trailing filename chr dir4: call printbc ;char printed - inr b - mov a,b - cpi 12 - jnc dir5 + inc b + ld a,b + cp 12 + jp nc,dir5 ;check for break between names - cpi 9 ;for another char - jnz dir3 + cp 9 ;for another char + jp nz,dir3 ;print a blank between names call blank - jmp dir3 + jp dir3 dir5: ;end of current entry - pop psw ;discard the directory counter (mod 4) + pop af ;discard the directory counter (mod 4) dir6: call break_key ;check for interrupt at keyboard - jnz endir ;abort directory search + jp nz,endir ;abort directory search call searchn ;for another entry - jmp dir2 + jp dir2 endir: ;end of directory scan - pop d ;discard directory counter - jmp retcom + pop de ;discard directory counter + jp retcom erase: call fillfcb0 ;cannot be all ???'s - cpi 11 - jnz erasefile + cp 11 + jp nz,erasefile ;erasing all of the disk - lxi b,ermsg + ld bc,ermsg call print call readcom - lxi h,comlen ;bad input - dcr m - jnz ccp - inx h - mov a,m - cpi 'Y' - jnz ccp + ld hl,comlen ;bad input + dec (hl) + jp nz,ccp + inc hl + ld a,(hl) + cp 'Y' + jp nz,ccp ;ok, erase the entire diskette - inx h ;otherwise error at retcom - shld comaddr + inc hl ;otherwise error at retcom + ld (comaddr),hl erasefile: call setdisk - lxi d,comfcb + ld de,comfcb call delete - inr a ;255 returned if not found - cz nofile ;no file message if so - jmp retcom + inc a ;255 returned if not found + call z,nofile ;no file message if so + jp retcom ermsg: db "ALL (Y/N)?",0 type: call fillfcb0 ;don't allow ?'s in file name - jnz comerr + jp nz,comerr call setdisk ;open the file call openc - jz typerr ;zero flag indicates not found + jp z,typerr ;zero flag indicates not found ;file opened, read 'til eof call crlf ;read first buffer - lxi h,bptr - mvi m,255 + ld hl,bptr + ld (hl),255 type0: ;loop on bptr - lxi h,bptr ;end buffer - mov a,m - cpi 128 - jc type1 ;carry if 0,1,...,127 - push h + ld hl,bptr ;end buffer + ld a,(hl) + cp 128 + jp c,type1 ;carry if 0,1,...,127 + push hl ;read another buffer full call diskreadc - pop h ;recover address of bptr - jnz typeof ;hard end of file - xra a ;bptr = 0 - mov m,a + pop hl ;recover address of bptr + jp nz,typeof ;hard end of file + xor a ;bptr = 0 + ld (hl),a type1: ;read character at bptr and print - inr m ;bptr = bptr + 1 - lxi h,buff ;h,l addresses char + inc (hl) ;bptr = bptr + 1 + ld hl,buff ;h,l addresses char call addh - mov a,m - cpi eofile - jz retcom + ld a,(hl) + cp eofile + jp z,retcom call printchar call break_key ;abort if break - jnz retcom - jmp type0 ;for another character + jp nz,retcom + jp type0 ;for another character typeof: ;end of file, check for errors - dcr a - jz retcom + dec a + jp z,retcom call readerr typerr: call resetdisk - jmp comerr + jp comerr save: call getnumber ; value to register a - push psw ;save it for later + push af ;save it for later ;should be followed by a file to save the memory image call fillfcb0 - jnz comerr ;cannot be ambiguous + jp nz,comerr ;cannot be ambiguous call setdisk ;may be a disk change - lxi d,comfcb ;existing file removed - push d + ld de,comfcb ;existing file removed + push de call delete - pop d + pop de call make ;create a new file on disk - jz saverr ;no directory space - xra a ;clear next record field - sta comrec - 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 + jp z,saverr ;no directory space + xor a ;clear next record field + ld (comrec),a + 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 - mov a,h ;may be completed - ora l - jz save1 - dcx h ;sector count = sector count - 1 - push h ;save it for next time around - lxi h,128 ;next dma address saved - dad d - push h + ld a,h ;may be completed + or l + jp z,save1 + dec hl ;sector count = sector count - 1 + push hl ;save it for next time around + ld hl,128 ;next dma address saved + add hl,de + push hl call setdma ;current dma address set - lxi d,comfcb + ld de,comfcb call diskwrite - pop d ;dma address, sector count - pop h - jnz saverr ;may be disk full case - jmp save0 ;for another sector + pop de ;dma address, sector count + pop hl + jp nz,saverr ;may be disk full case + jp save0 ;for another sector save1: ;end of dump, close the file - lxi d,comfcb + ld de,comfcb call close - inr a ;255 becomes 00 if error - jnz retsave ;for another command + inc a ;255 becomes 00 if error + jp nz,retsave ;for another command saverr: ;must be full or read only disk - lxi b,fullmsg + ld bc,fullmsg call print retsave: ;reset dma buffer call setdmabuff - jmp retcom + jp retcom fullmsg: db "NO SPACE",0 @@ -1062,189 +1065,189 @@ fullmsg: rename: ;rename a file on a specific disk call fillfcb0 ;must be unambiguous - jnz comerr - lda sdisk ;save for later compare - push psw + jp nz,comerr + ld a,(sdisk) ;save for later compare + push af call setdisk ;disk selected call searchcom ;is new name already there? - jnz renerr3 + jp nz,renerr3 ;file doesn't exist, move to second half of fcb - lxi h,comfcb - lxi d,comfcb+16 - mvi b,16 + ld hl,comfcb + ld de,comfcb+16 + ld b,16 call move0 ;check for = or left arrow - lhld comaddr - xchg + ld hl,(comaddr) + ex de,hl call deblank - cpi '=' ;ok if = - jz ren1 - cpi la - jnz renerr2 -ren1: xchg ;past delimiter - inx h - shld comaddr + cp '=' ;ok if = + jp z,ren1 + cp la + jp nz,renerr2 +ren1: ex de,hl ;past delimiter + inc hl + ld (comaddr),hl ;proper delimiter found call fillfcb0 - jnz renerr2 + jp nz,renerr2 ;check for drive conflict - pop psw ;previous drive number - mov b,a - lxi h,sdisk - mov a,m - ora a - jz ren2 + pop af ;previous drive number + ld b,a + ld hl,sdisk + ld a,(hl) + or a + jp z,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 ;is old file there? - sta comfcb + cp b + ld (hl),b + jp nz,renerr2 +ren2: ld (hl),b ;store the name in case drives switched + xor a ;is old file there? + ld (comfcb),a call searchcom - jz renerr1 + jp z,renerr1 ;everything is ok, rename the file - lxi d,comfcb + ld de,comfcb call renam - jmp retcom + jp retcom renerr1:; no file on disk call nofile - jmp retcom + jp retcom renerr2:; ambigous reference/name conflict call resetdisk - jmp comerr + jp comerr renerr3:; file already exists - lxi b,renmsg + ld bc,renmsg call print - jmp retcom + jp retcom renmsg: db "FILE EXISTS",0 user: ;set user number call getnumber ; leaves the value in the accumulator - cpi 16 ; must be between 0 and 15 - jnc comerr - mov e,a ;save for setuser call - lda comfcb+1 - cpi ' ' - jz comerr + cp 16 ; must be between 0 and 15 + jp nc,comerr + ld e,a ;save for setuser call + ld a,(comfcb+1) + cp ' ' + jp z,comerr call setuser ;new user number set - jmp endcom + jp endcom userfunc: ifndef noserialize call serialize ;check serialization endif ;load user function and set up for execution - lda comfcb+1 - cpi ' ' - jnz user0 + ld a,(comfcb+1) + cp ' ' + jp nz,user0 ;no file name, but may be disk switch - lda sdisk ;no disk name if 0 - ora a - jz endcom - dcr a ;set user/disk - sta cdisk + ld a,(sdisk) ;no disk name if 0 + or a + jp z,endcom + dec a ;set user/disk + ld (cdisk),a call setdiska call select - jmp endcom + jp endcom user0: ;file name is present - lxi d,comfcb+9 ;type ' ' - ldax d - cpi ' ' - jnz comerr - push d ;.com + ld de,comfcb+9 ;type ' ' + ld a,(de) + cp ' ' + jp nz,comerr + push de ;.com call setdisk - pop d - lxi h,comtype + pop de + ld hl,comtype call movename ;file type is set to .com call openc - jz userer + jp z,userer ;file opened properly, read it into memory - lxi h,tran ;transient program base -load0: push h ;save dma address - xchg + ld hl,tran ;transient program base +load0: push hl ;save dma address + ex de,hl call setdma - lxi d,comfcb + ld de,comfcb call diskread - jnz load1 + jp nz,load1 ;sector loaded, set new dma address and compare - pop h - lxi d,128 - dad d - lxi d,tranm ;has the load overflowed? - mov a,l + pop hl + ld de,128 + add hl,de + ld de,tranm ;has the load overflowed? + ld a,l sub e - mov a,h - sbb d - jnc loaderr - jmp load0 ;for another sector - -load1: pop h ;end file is 1 - dcr a - jnz loaderr + ld a,h + sbc a,d + jp nc,loaderr + jp load0 ;for another sector + +load1: pop hl ;end file is 1 + dec a + jp nz,loaderr call resetdisk ;back to original disk call fillfcb0 - lxi h,sdisk - push h - mov a,m ;drive number set - sta comfcb - mvi a,16 ;move entire fcb to memory + ld hl,sdisk + push hl + ld a,(hl) ;drive number set + ld (comfcb),a + ld a,16 ;move entire fcb to memory call fillfcb - pop h - mov a,m - sta comfcb+16 - xra a ;record number set to zero - sta comrec - lxi d,fcb - lxi h,comfcb - mvi b,33 + pop hl + ld a,(hl) + ld (comfcb+16),a + xor a ;record number set to zero + ld (comrec),a + ld de,fcb + ld hl,comfcb + ld b,33 call move0 ;move command line to buff - lxi h,combuf -bmove0: mov a,m - ora a - jz bmove1 - cpi ' ' - jz bmove1 - inx h ;for another scan - jmp bmove0 + ld hl,combuf +bmove0: ld a,(hl) + or a + jp z,bmove1 + cp ' ' + jp z,bmove1 + inc hl ;for another scan + jp bmove0 ;first blank position found -bmove1: mvi b,0 ;ready for the move - lxi d,buff+1 -bmove2: mov a,m - stax d - ora a - jz bmove3 +bmove1: ld b,0 ;ready for the move + ld de,buff+1 +bmove2: ld a,(hl) + ld (de),a + or a + jp z,bmove3 ;more to move - inr b - inx h - inx d - jmp bmove2 + inc b + inc hl + inc de + jp bmove2 bmove3: ;b has character count - mov a,b - sta buff + ld a,b + ld (buff),a 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 + ld sp,stack ;may come back here call setdiska call select - jmp ccp + jp ccp userer: ;arrive here on command error call resetdisk - jmp comerr + jp comerr loaderr:;cannot load the program - lxi b,loadmsg + ld bc,loadmsg call print - jmp retcom + jp retcom loadmsg: db "BAD LOAD",0 comtype: @@ -1256,13 +1259,13 @@ retcom: ;reset disk before end of command check endcom: ;end of intrinsic command call fillfcb0 ;to check for garbage at end of line - lda comfcb+1 - sui ' ' - lxi h,sdisk - ora m + ld a,(comfcb+1) + sub ' ' + ld hl,sdisk + or (hl) ;0 in accumulator if no disk selected, and blank fcb - jnz comerr - jmp ccp + jp nz,comerr + jp ccp @@ -1287,4 +1290,4 @@ 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 + end diff --git a/ccp.sym b/ccp.sym new file mode 100644 index 0000000..7137850 --- /dev/null +++ b/ccp.sym @@ -0,0 +1,197 @@ +loadmsg: EQU 0x0000F07F +bmove3: EQU 0x0000F054 +bmove2: EQU 0x0000F048 +bmove1: EQU 0x0000F043 +bmove0: EQU 0x0000F035 +loaderr: EQU 0x0000F076 +load1: EQU 0x0000F006 +load0: EQU 0x0000EFE6 +userer: EQU 0x0000F070 +comtype: EQU 0x0000F088 +user0: EQU 0x0000EFC9 +endcom: EQU 0x0000F08E +renmsg: EQU 0x0000EF87 +renerr1: EQU 0x0000EF72 +ren2: EQU 0x0000EF5E +renerr2: EQU 0x0000EF78 +ren1: EQU 0x0000EF44 +renerr3: EQU 0x0000EF7E +fullmsg: EQU 0x0000EF0C +retsave: EQU 0x0000EF06 +save1: EQU 0x0000EEF6 +save0: EQU 0x0000EED9 +saverr: EQU 0x0000EF00 +typeof: EQU 0x0000EEA5 +type1: EQU 0x0000EE8C +type0: EQU 0x0000EE79 +bptr: EQU 0x0000F0F6 +typerr: EQU 0x0000EEAC +ermsg: EQU 0x0000EE57 +erasefile: EQU 0x0000EE47 +retcom: EQU 0x0000F08B +dir5: EQU 0x0000EE13 +dirb: EQU 0x0000EDFC +dir4: EQU 0x0000EDFE +dir3: EQU 0x0000EDDE +dirhdr1: EQU 0x0000EDD9 +dirhdr0: EQU 0x0000EDD1 +dir6: EQU 0x0000EE14 +endir: EQU 0x0000EE20 +dir2: EQU 0x0000ED9C +dir0: EQU 0x0000ED8C +dir1: EQU 0x0000ED93 +resetdisk: EQU 0x0000ED6A +setdisk: EQU 0x0000ED58 +addhcf: EQU 0x0000ED4F +movename: EQU 0x0000ED44 +conv1: EQU 0x0000ED37 +conv0: EQU 0x0000ED0C +getnumber: EQU 0x0000ECFC +nofmsg: EQU 0x0000ECF4 +nofile: EQU 0x0000ECEE +rdmsg: EQU 0x0000ECE3 +readerr: EQU 0x0000ECDD +user: EQU 0x0000EF93 +rename: EQU 0x0000EF15 +save: EQU 0x0000EEB2 +type: EQU 0x0000EE62 +erase: EQU 0x0000EE24 +direct: EQU 0x0000ED7B +jmptab: EQU 0x0000ECC5 +userfunc: EQU 0x0000EFAA +ccp0: EQU 0x0000EC9C +stack: EQU 0x0000F0B0 +intrin3: EQU 0x0000EC54 +intrin2: EQU 0x0000EC4F +intrin1: EQU 0x0000EC3C +intrin0: EQU 0x0000EC33 +intrinsic: EQU 0x0000EC2E +intlen: EQU 0x00000006 +intvec: EQU 0x0000EC10 +scnq0: EQU 0x0000EC09 +scnq: EQU 0x0000EC01 +efill0: EQU 0x0000EBF2 +efill: EQU 0x0000EBF0 +trtyp: EQU 0x0000EBDF +setty2: EQU 0x0000EBDB +setty1: EQU 0x0000EBD9 +setty0: EQU 0x0000EBC8 +padty: EQU 0x0000EBE9 +setty: EQU 0x0000EBC0 +trname: EQU 0x0000EBAF +setnam2: EQU 0x0000EBAB +setnam1: EQU 0x0000EBA9 +padname: EQU 0x0000EBB9 +setnam0: EQU 0x0000EB98 +setname: EQU 0x0000EB96 +setcur: EQU 0x0000EB88 +setdsk: EQU 0x0000EB90 +setcur0: EQU 0x0000EB89 +sdisk: EQU 0x0000F0F5 +fillfcb: EQU 0x0000EB60 +fillfcb0: EQU 0x0000EB5E +addh: EQU 0x0000EB59 +deblank: EQU 0x0000EB4F +delim: EQU 0x0000EB30 +comerr1: EQU 0x0000EB22 +comerr0: EQU 0x0000EB0F +comerr: EQU 0x0000EB09 +badserial: EQU 0x0000ECD3 +ser0: EQU 0x0000EAFD +serial: EQU 0x0000EC28 +serialize: EQU 0x0000EAF5 +setdma: EQU 0x0000EAD8 +setdmabuff: EQU 0x0000EAD5 +cselect: EQU 0x0000EAD0 +readcom1: EQU 0x0000EABA +readcom0: EQU 0x0000EAAB +ccp: EQU 0x0000EC86 +del_sub: EQU 0x0000EADD +noread: EQU 0x0000EAA7 +break_key: EQU 0x0000EAC2 +submod: EQU 0x0000F0BF +move0: EQU 0x0000ED46 +subcr: EQU 0x0000F0D1 +subrc: EQU 0x0000F0C0 +subfcb: EQU 0x0000F0B1 +nosub: EQU 0x0000EA96 +submit: EQU 0x0000F0B0 +readcom: EQU 0x0000EA39 +translate: EQU 0x0000EA30 +setdiska: EQU 0x0000EA29 +cdisk: EQU 0x0000F0F4 +saveuser: EQU 0x0000EA1A +setuser: EQU 0x0000EA15 +getuser: EQU 0x0000EA13 +renam: EQU 0x0000EA0E +make: EQU 0x0000EA09 +diskwrite: EQU 0x0000EA04 +diskreadc: EQU 0x0000E9FE +diskread: EQU 0x0000E9F9 +bdos_cond: EQU 0x0000E9F4 +delete: EQU 0x0000E9EF +searchcom: EQU 0x0000E9E9 +searchn: EQU 0x0000E9E4 +search: EQU 0x0000E9DF +close: EQU 0x0000E9DA +comfcb: EQU 0x0000F0D2 +comrec: EQU 0x0000F0F2 +openc: EQU 0x0000E9D0 +open: EQU 0x0000E9CB +dcnt: EQU 0x0000F0F3 +bdos_inr: EQU 0x0000E9C3 +select: EQU 0x0000E9BD +initialize: EQU 0x0000E9B8 +prin0: EQU 0x0000E9AC +print: EQU 0x0000E9A7 +blank: EQU 0x0000E9A2 +crlf: EQU 0x0000E998 +printbc: EQU 0x0000E992 +printchar: EQU 0x0000E98C +eofile: EQU 0x0000001A +la: EQU 0x0000005F +lf: EQU 0x0000000A +cr: EQU 0x0000000D +sysfile: EQU 0x0000000A +rofile: EQU 0x00000009 +userf: EQU 0x00000020 +dmaf: EQU 0x0000001A +cself: EQU 0x00000019 +logf: EQU 0x00000018 +renf: EQU 0x00000017 +makef: EQU 0x00000016 +dwritf: EQU 0x00000015 +dreadf: EQU 0x00000014 +delf: EQU 0x00000013 +searnf: EQU 0x00000012 +searf: EQU 0x00000011 +closef: EQU 0x00000010 +openf: EQU 0x0000000F +self: EQU 0x0000000E +initf: EQU 0x0000000D +liftf: EQU 0x0000000C +breakf: EQU 0x0000000B +rbuff: EQU 0x0000000A +pbuff: EQU 0x00000009 +pcharf: EQU 0x00000002 +rcharf: EQU 0x00000001 +fcb: EQU 0x0000005C +buff: EQU 0x00000080 +bdos: EQU 0x00000005 +diska: EQU 0x00000004 +staddr: EQU 0x0000E98A +comaddr: EQU 0x0000E988 +combuf: EQU 0x0000E908 +comlen: EQU 0x0000E907 +maxlen: EQU 0x0000E906 +ccpclear: EQU 0x0000EC58 +ccpstart: EQU 0x0000EC5C +ccploc: EQU 0x0000E900 +tranm: EQU 0x0000E900 +tran: EQU 0x00000100 +bdosl: EQU 0x0000E000 +BDOS_ORG: EQU 0x0000E000 +CCP_ORG: EQU 0x0000E900 +testing: EQU 0x00000000 +_true: EQU 0xFFFFFFFF +_false: EQU 0x00000000