home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
F
/
PETASCII.ARK
/
PETASCII.MAC
< prev
Wrap
Text File
|
1987-09-17
|
23KB
|
893 lines
;
; PETASCII.MAC -- Version 1.0
;
; USAGE:
;
; PETASCII {d:}<fn.ft> {d:}{<fn.ft>}
;
; Copies the input file (first file reference) to the output file
; (second file reference), converting PETASCII characters to ASCII
; characters. Also inserts linefeeds after carriage returns where
; they do not already exist.
;
; If the drivecode d: of the input file is omitted the current drive
; is assumed. An input filename is required.
;
; If the output file reference is omitted, it will be given the same
; name as the input file. Any file of the same name on the destination
; drive will be renamed to filetype .BAK, which will preserve the
; input file if both input and output use the same drive. If the
; output filename does not include a filetype, the output file will
; be given the same filetype as the input file. If a drive speci-
; fication is not given, output will default to the current drive.
;
; Version 1.0, 9/17/87, Gene Pizzetta -- for the I/O routines I have
; relied heavily on David E. Cortesi, "A Programmer's Notebook:
; Utilities for CP/M-80"
;
; This program was developed using SLRMAC from SLR Systems. I will
; also assemble with MAC, but you will need to have Z80.LIB on your
; default disk.
;
WarmStart equ 0000h ; vector to BIOS re-boot
CpmBasePage equ high WarmStart
Bdos equ 0005h ; vector to CP/M BDOS
BdosAddress equ 0006h ; address in the Bdos jump
CpmFcb equ 005Ch ; default FCB, file operand 1
CpmFcb2 equ CpmFcb+10h ; file operand 2
CpmBuffer equ 0080h ; default file buffer 80..FFh
CpmTail equ CpmBuffer ; command tail
TransientArea equ 0100h ; start of the .COM file
SuccessCode equ 0000h ; program success code
FailCode equ 0FF00h ; program failure code
;
; BDOS functions
BdosKeyin equ 01h ; one console input byte
BdosType equ 02h ; type byte at console
BdosPrint equ 05h ; print one byte
BdosString equ 09h ; type "string$" at console
BdosLine equ 0Ah ; read a buffered console line
BdosTestCon equ 0Bh ; test console, A > 0 if key hit
BdosSetDrive equ 0Eh ; select default drivecode
BdosOpen equ 0Fh ; open a disk file
BdosClose equ 10h ; close (output) file
BdosSrch1 equ 11h ; initial directory search
BdosSrchn equ 12h ; successive directory searches
BdosErase equ 13h ; erase a file
BdosRead equ 14h ; read disk sequential
BdosWrite equ 15h ; write disk sequential
BdosMake equ 16h ; create a file directory entry
BdosRename equ 17h ; rename file
BdosDrive equ 19h ; get default drive number
BdosSetBuffer equ 1Ah ; set file buffer address
BdosGetAlloc equ 1Bh ; get address of allocation vector
BdosGetDPB equ 1Fh ; get address of DPB
BdosFreeSpace equ 2Eh ; get disk free space
BdosReturn equ 6Ch ; program return code
BdosParse equ 98h ; parse filename
;
; ASCII values
AsciiLF equ 0Ah ; LineFeed
AsciiCR equ 0Dh ; CarriageReturn
CpmEof equ 1Ah ; ^Z, end of ascii file
AsciiBlank equ 20h ; blank
AsciiDEL equ 7Fh ; DEL, highest valid byte
;
MACLIB Z80
;
; Program entry macro: find bottom of Bdos and set the stack
; there. Call label Main with HL --> end of storage. Provide
; code to support the ABORT macro and the command tail.
;
PROLOG MACRO
ORG TransientArea ;; start at TPA
LHLD BdosAddress ;; HL --> BDOS base
MVI L,255
INX H ;; HL --> page above BDOS
DCR H ;; HL --> page below BDOS
SPHL ;; SP --> high storage
DCR H ;; Allow 256 byte stack
DCX H ;; HL --> last usable byte
CALL Main ;; call mainline code
;
; On normal exit, the main routine will return here ...
EPILOG:
JMP WarmStart ;; do a warm start
;
; If a fatal error is detected the ABORT macro will come
; here, with the address of a "message$" string on top of
; the stack and all registers as they were. When debugging
; with DDT, set a breakpoint here to trap an abort. When
; using SID, set a pass-counter at label ERROREXIT.
;
ERROREXIT:
POP D ;; type the string on
MVI C,BdosString ;; ..the console
CALL Bdos
LXI D,FailCode ;; kill any active
MVI C,BdosReturn ;; ..submit file
CALL Bdos
JMP WarmStart ;; and terminate
ENDM
;
; Bdos-service macro: call Bdos for a service, saving all
; registers except A and sometimes HL. Load DE with the
; service parameter if one was specified.
;
SERVICE MACRO ?S,?DE
PUSH B
PUSH D
IF (?S NE 12) AND (?S NE 24) AND (?S NE 27)
IF (?S NE 29) AND (?S NE 31)
PUSH H
ENDIF
ENDIF
IF NOT NUL ?DE
LXI D,?DE
ENDIF
MVI C,?S
CALL Bdos
IF (?S NE 12) AND (?S NE 24) AND (?S NE 27)
IF (?S NE 29) AND (?S NE 31)
POP H
ENDIF
ENDIF
POP D
POP B
ENDM
;
; Abort-the-program-with-a-message macro: The operand
; is the address of a message in storage.
;
; The macro puts the address of the message on the
; stack, preserving all registers for use in debugging. It
; branches to the ERROREXIT assembled by PROLOG, where the
; message will be printed.
;
ABORT MACRO ?MSG
PUSH H
LXI H,?MSG
XTHL
JMP ERROREXIT
ENDM
;
; Macro to make it easy to origin the assembler to the next
; page boundary.
;
ORGPAGE MACRO
ORG ($+255) AND 0FF00h
ENDM
;
; Macro to test the console and, if a key has been hit, to
; jump to a named location. No registers are changed, so
; the macro can be inserted anywhere in the code.
;
TESTCON MACRO WHERE
local skippit
local endtest
push h
push d
push b
push psw
mvi c,BdosTestCon
call Bdos ;; test the console
lxi h,endtest ;; assume no key hit
ora a ;; was one?
JRZ skippit ;; jump if not
lxi h,WHERE ;; yes, prepare to exit
skippit pop psw ;; restore A, flags,
pop b ;; regs BC,
pop d ;; ..and DE
xthl ;; restore H, stack address
ret ;; go to 'endtest' or WHERE
endtest equ $
ENDM
;
; Program begins here ...
;
PROLOG
;
; Input Variables: used by SetUpInput and GetChar.
;
PFCB dw CpmBuffer+1 ; FCB addresses for BdosParse
dw 0 ; (service function 152)
InFCB ds 36 ; Input FCB
InIndex db 0 ; Index over CpmBuffer
;
; Output Variables: used by SetUpOutput, PutChar, DumpOut.
;
OutFCB ds 36 ; Output FCB
OutType ds 3 ; hold for real output filetype
OutBuffer dw 0 ; address of OutBuffer
OutIndex dw 0 ; index over OutBuffer
OutLimit dw 0 ; negative of size of OutBuffer
DollarType db '$$$' ; type of an output workfile
BAKType db 'BAK' ; type of BAK file
;
; Messages:
;
MsgNoName db 'An input filename is required.$'
MsgNoFile db 'Input file not found.$'
MsgNoBuffer db 'Not enough room for an output buffer.$'
MsgNoParseIn db 'Illegal input filename.$'
MsgNoParseOut db 'Illegal output filename.$'
MsgAmbig db 'The output file may not be ambiguous.$'
MsgNoMake db 'Can''t create the work file.$'
MsgWrite db 'Error writing the work file.$'
MsgNoClose db 'Error closing the work file.$'
MsgRename db 'Error renaming work file to proper name.$'
MsgRenameEx db 'Error renaming existing file to .BAK.$'
MsgSignOn: db 'PETASCII Version 1.0',AsciiCR,AsciiLF,'$'
;
; the main program -- initialization
;
Main: lxi d,MsgSignOn ; print sign on message
mvi c,BdosString
call Bdos
;
call SetUpInput ; open the input file
lxi b,InFCB ; BC --> default fileref
lxi d,OBspace ; DE --> start of buffer space
; prolog sets HL --> end of buffer space
call SetUpOutput ; prepare the output stuff
;
; the main program -- main loop
;
call GetChar ; get first character
;
MainWhile:
cpi CpmEof ; while not EOF ...
JRZ MainEnd
;
cpi AsciiCR ; is it a carriage return?
JRZ IsReturn ; (yes, handle it)
;
cpi 041h ; is it control, number, symbol?
JRC MainPut ; (yes, print it)
;
cpi 05Bh ; is it PETASCII lowercase?
JRC MakeLower ; (yes, make ASCII lower)
;
cpi 061h ; is it a symbol?
JRC MainPut ; (yes, print it)
;
cpi 07Bh ; is it PETASCII low uppercase?
JRC MakeUpper1 ; (yes, make ASCII upper)
;
cpi 0C1h ; is it a symbol?
JRC ClearHigh ; (yes, handle it)
;
cpi 0DBh ; is it PETASCII high uppercase?
JRC MakeUpper2 ; (yes, make ASCII upper)
;
JR ClearHigh ; handle any leftovers
;
; MakeLower: it's a PETASCII lowercase character which we make
; into ASCII lowercase by adding 32 to it ...
;
MakeLower:
adi 20h
JR MainPut
;
; MakeUpper1: it's a PETASCII uppercase character in the 61h-7Ah
; range which we make into ASCII uppercase by subtracting 32 ...
;
MakeUpper1:
sui 20h
JR MainPut
;
; MakeUpper2: it's a PETASCII uppercase character in the C1h-DAh
; range which we make into ASCII uppercase by substracting 128 ...
;
MakeUpper2:
sui 80h
JR MainPut
;
; IsReturn: it's a carriage return. We send it and then determine
; if the next character is a linefeed. If it's not, we send one.
;
IsReturn:
call PutChar ; send the carriage return
call GetChar ; get the next character
cpi AsciiLF ; is it a linefeed?
JRZ MainPut ; (yes, send it)
push psw ; no, save the character
mvi a,AsciiLF
call PutChar ; send a linefeed
pop psw ; recover character
jmp MainWhile ; ..and loop
;
; ClearHigh: we have a character with the high bit set so we must
; reset it and fall through to send it ...
;
ClearHigh:
ani AsciiDEL
;
; MainPut: we come here with the adjusted character in A. We
; must send it, get the next character, and loop ...
;
MainPut:
call PutChar
call GetChar
jmp MainWhile ; ..end while
;
MainEnd:
call FinishOutput ; complete output file
ret ; end main
;
; I/O subroutines --
;
; GetChar: return the next byte of input in A. The default
; buffer at 80h..FFh is used. Since we are dealing with ASCII
; files, CpmEof (^Z) is the end of file mark. When it appears,
; don't advance the index past it, so further call will keep on
; returning CpmEof indefinitely.
; Preserves: BC, DE, HL
;
GetChar:
push h ; save a work register
lda InIndex
inr a ; InIndex = InIndex + 1
JRNZ GetChar2
;
; InIndex was FFh, the buffer is empty. Put EOF in the buffer
; so that if physical end of file occurs, we will see it as
; logical end of file instead.
;
push d
push b
lxi h,CpmBuffer
mvi m,CpmEof ; put CpmEof in buffer
xchg ; DE --> buffer
mvi c,BdosSetBuffer
call Bdos ; set buffer address
lxi d,InFCB
mvi c,BdosRead
call Bdos ; read a record
pop b
pop d
mvi a,80h ; InIndex = 80h
;
; At this point there is either data or CpmEof at the
; location addressed by InIndex = A.
;
GetChar2:
sta InIndex
mvi h,CpmBasePage ; form an address
mov l,a
mov a,m ; A = data
cpi CpmEof ; if it's EOF,
JRNZ GetChar3
lxi h,InIndex
dcr m ; ..InIndex = InIndex - 1
GetChar3:
pop h
ret
;
; PutChar: write the byte in A into the output buffer. If the
; buffer is full, (OutIndex=OutLimit), then dump it first.
; Preserves: All
;
PutChar:
push h
push d
lhld OutIndex
xchg ; DE = OutIndex
lhld OutLimit
dad d ; carry = OutIndex=OutLimit
JRNC PutChar2
;
call DumpOut ; dump the buffer to the file
lxi d,0 ; OutIndex = 0
;
PutChar2:
lhld OutBuffer
dad d ; HL --> next output byte spot
mov m,a
inx d
xchg
shld OutIndex ; OutIndex = OutIndex +1
pop d
pop h
ret
;
; DumpOut: write buffered output data to the work file. Called
; in two cases: (1) when the buffer is full (OutIndex=OutLimit)
; and (2) at the end of the program when OutIndex is
; unpredictable and might even be zero. The buffer must be a
; multiple of 128 bytes, but needn't be on any special boundary.
; Preserves: All
;
DumpOut:
push psw
push h
push d
push b
lhld OutIndex
mov a,h
ora l ; is there any data at all?
JRZ DumpOut9 ; ..no data? do nothing.
;
; When the buffer is full, OutIndex mod 128 is zero. At the
; end of the run, though, OutIndex could be in mid-record. In
; that case, fill the last record with EOF marks.
;
xchg ; DE = OutIndex
lhld OutBuffer
dad d ; HL --> next output byte
DumpOut2:
mov a,e
ani 128-1 ; test OutIndex mod 128
JRZ DumpOut3 ; (it was zero)
mvi m,CpmEof ; ..stick in an EOF
inx d ; ..step OutIndex
inx h ; .. and step storage pointer
JR DumpOut2
;
; The buffer now contains a whole number of 128-byte records.
; Write them all. Keep the limit index in BC, and the current
; record's index in DE.
;
DumpOut3:
mov b,d ; BC = index of last record
mov c,e
dcx b ; ..less one
lxi d,0 ; DE = starting index of 0
DumpOut4:
lhld OutBuffer
dad d
xchg ; DE --> record, HL has index
SERVICE BdosSetBuffer
SERVICE BdosWrite,OutFCB
ora a ; check for disk full, etc.
JRNZ DumpOutError
;
lxi d,128
dad d ; step index (in HL)
xchg ; DE = index to next record
call CmpBD ; set flags fro BC vs DE
JRNC DumpOut4 ; continue if limit <= index
;
DumpOut9:
pop b
pop d
pop h
pop psw
ret
;
DumpOutError:
ABORT MsgWrite
;
; CmpBD: compare BC to DE as a 16-bit unsigned integer, setting
; the machine flags as for a CMP instruction.
; Preserves: All except the flags
;
CmpBD:
push h
mov h,a
mov a,b
cmp d
JRNZ CmpBDZ
mov a,c
cmp e
CmpBDZ: mov a,h
pop h
ret
;
; SetUpInput: initialize the input file for utility I/O with
; GetChar. Requires definition of InFCB, InIndex (InVars).
; Preserves: All
;
SetUpInput:
push psw
push b
push d
push h
;
; Prepare the input file for reading
;
lxi h,InFCB ; put addr of InFCB into PFCB
shld PFCB+2
lxi d,PFCB ; parse filename to InFCB
mvi c,BdosParse
call Bdos
;
; If input filename omitted, abort
;
shld PFCB ; save return code
mvi a,0FFh ; check return code
cmp h
JRNZ SUI1 ; parsed okay
cmp l
JRNZ SUI1
ABORT MsgNoParseIn
SUI1: lxi h,InFCB+1
mvi a,AsciiBlank
cmp m
JRNZ SUI2 ; parse successful, continue
ABORT MsgNoName
;
; get an input drivecode for the FCB
;
SUI2: dcx h
mov a,m ; A = given drivecode
ora a ; was it omitted?
JRNZ SUI3
SERVICE BdosDrive ; get, e.g., A=00, B=01
inr a ; make it A=01, B=02, etc.
SUI3:
sta InFCB ; explicit drivecode in FCB
;
; open the input FCB
;
SERVICE BdosOpen,InFCB
inr a ; if no file exists, abort
JRNZ SUI4
ABORT MsgNoFile
;
; InIndex = FFh
;
SUI4:
mvi a,0FFh
sta InIndex
;
pop h
pop d
pop b
pop psw
ret
;
; FillZero: replicate 00h, beginning at DE, for BC bytes
;
FillZero:
push psw
xra a
JR FillX
;
; FillA: replicate the byte in A, beginning at DE, for BC bytes.
; If the length is 2 or greater, use MoveHtoD to do the work. If
; the length is 1, that won't work.
; Preserves: A, BC, HL
; Returns: DE advanced by BC
;
FillA:
push psw
FillX: ; FillZero joins here
push h
stax d ; fill one byte
inx d ; ..step,
dcx b ; ..count the one
mov h,a ; save fill byte
mov a,b ; guard against case of BC=0001
ora c
JRZ FillZ
mov a,h ; recover fill byte
mov h,d ; create address of fill data
mov l,e ; ..in storage
dcx h ; HL --> first byte, DE --> second
call MoveHtoD ; do propogation-move
FillZ: inx b ; restore entry value of b
pop h
pop psw
ret
;
; MoveHtoD: Z80 LDIR instruction. It does [HL++] --> [DE++] for
; BC times. BC must be 1 or more. BC is preserved. That is handy for
; repetitive use of the routine.
;
MoveHtoD:
push b
ldir
pop b
ret
;
; Delimiter: HL addresses a byte. Find out if it is one of the
; standard CP/M token delimiters.
; Preserves: BC, DE, HL
; Returns: Z flag true if byte is a delimiter
; A = the byte itself
; Note: The tests are made in descending order by ASCII value.
; This "rnc" returns if the byte is equal, or if it is greater
; and hence cannot possibly be one of the bytes tested later.
;
Delimiter:
mov a,m
cpi ']' ; delimiters for option lists
rnc
cpi '['
rnc
cpi '=' ; delimits filerefs in, e.g., ren
rnc
cpi ';' ; delimits passwords (BDOS 3)
rnc
cpi '/' ; delimits optional parameters
rnc
cpi '.' ; delimits filetypes
rnc
cpi ',' ; delimits tokens (supposedly)
rnc
cpi ' ' ; only token delimiter that works
rnc
cmp a ; control character -- force Z true
ret
;
; SetUpOutput: prepare the utility output mechanism.
; A missing filetype from the command line will be filled in with
; the filetype of the input file (from InFCB).
; Input: DE --> start of output buffer
; HL --> end of output buffer (as PROLOG gives it)
; CpmFcb2 contains output fileref
; Preserves: All
; Note: this code assumes that the OutVars and FileMessages
; units from this file have been included.
; It aborts the program under these conditions:
; MsgAmbigOut, if the output fileref is ambiguous
; MsgNoBuffer, if the output buffer is less than 256 bytes
; MsgNoMake, if "outname.$$$" can't be defined
; MsgNoClose, if "outname.$$$" doesn't close successfully
; MsgNoRename, if the rename to change the type doesn't work
; MsgNoParseIn, if input filename is illegal
; MsgNoParseOut, if output filename is illegal
;
SetUpOutput:
push psw
push b
push d
push h
;
; prepare the buffer address, index, and index limit. The limit
; is the 2s complement of the buffer-size -- see DumpOut for use
;
xchg ; HL --> start of buffer
mov a,l ; ensure buffer starts on 128-multiple
dcr a
ori 128-1
mov l,a
inx h
shld OutBuffer
xchg ; DE --> start, HL --> end
mov a,d
cma
mov d,a
mov a,e
cma
mov e,a
inx d ; DE = 2s complement of buffer start
dad d ; HL = buffer size
mov a,h ; ..which we want to ensure is at
ora a ; least 256 bytes ...
JRNZ SUO2 ; (it is)
ABORT MsgNoBuffer
SUO2:
mov a,l ; ensure buffer size is a multiple
ani 128 ; ..of 128 bytes, too
cma
mov l,a
mov a,h
cma
mov h,a
inx h
shld OutLimit ; OutLimit = 2s complement of size
lxi h,0
shld OutIndex ; OutIndex = 0
;
; fill filename and type in OutFCB with spaces
;
mvi a,AsciiBlank
lxi b,11
lxi d,OutFCB+1
call FillA
;
; make the rest of the FCB zeroes
;
lxi b,36-12
call FillZero
;
; see if there's an output fileref in the command tail and, if so,
; parse it into the OutFCB
;
lda PFCB ; is there more in the tail
cpi 0 ; if the return code = 0,
JRNZ SUO2a ; ..there's no more
lda PFCB+1
cpi 0
JRNZ SUO2a
JR SUO2b ; (no more, get default)
SUO2a: lxi h,OutFCB ; there's more ... try parsing
shld PFCB+2 ; ..it to see if it's a fileref
lxi d,PFCB
mvi c,BdosParse ; parse second fileref
call Bdos
mvi a,0FFh ; check return code
cmp h
JRNZ SUO2b ; parsed okay
cmp l
JRNZ SUO2b
ABORT MsgNoParseOut
;
; Get an output drivecode for the FCB
;
SUO2b: lxi h,OutFCB
mov a,m ; A = given drivecode
ora a ; was it omitted?
JRNZ SUO2c ; (no, store it)
SERVICE BdosDrive ; get, e.g., A=00, B=01
inr a ; make it A=01, B=02, etc.
;
SUO2c: sta OutFCB
;
; get an output filename for the FCB, and make sure that
; the name given is explicit (has no question marks).
;
SUO3:
lxi b,8
lxi d,OutFCB+1 ; DE --> destination
lxi h,InFCB+1 ; HL --> 2nd operand filename
lda OutFCB+1 ; was it omitted?
cpi AsciiBlank
cz MoveHtoD ; if so, copy over default
lxi h,OutFCB+1 ; HL --> the final filename
mvi a,'?' ; BC still has the length
call ScanForA ; look for "?" in name
JRNZ SUO4 ; (there are none)
ABORT MsgAmbig
;
; get an output filetype and save it. Make sure it isn't
; ambiguous, either.
;
SUO4:
lxi b,3 ; BC = length of filetype
lxi d,OutType ; DE --> destination (not FCB)
lxi h,OutFCB+9 ; HL --> 2nd operand filetype
mov a,m
cpi AsciiBlank ; was one given?
JRNZ SUO5 ; (yes, move it)
lxi h,InFCB+9 ; ..no, use default filetype
SUO5:
call MoveHtoD ; move filetype to OutType
lxi h,OutType ; ..then check the chosen type
mvi a,'?'
call ScanForA ; look for "?" in type
JRNZ SUO6 ; (none found)
ABORT MsgAmbig
;
; Prepare a workfile for output
; move '$$$' to the output FCB filetype
;
SUO6:
lxi h,DollarType ; "$$$" for use in work file
lxi d,OutFCB+9
lxi b,3 ; length of filetype
call MoveHtoD
;
; erase any existing workfile of that name
; (note: if drive is R/O, we die here)
;
SERVICE BdosErase,OutFCB
;
; make a file of the workfile's name
;
SERVICE BdosMake,OutFCB
inr a ; if the make fails, abort
JRNZ SUO7
ABORT MsgNoMake
;
SUO7:
pop h
pop d
pop b
pop psw
ret
;
; FinishOutput: close the work file and rename to proper type.
; Preserves: All
;
FinishOutput:
push psw
push b
push d
push h
;
call DumpOut ; write any buffered output
;
lxi d,OutFCB ; then close the work file
mvi c,BdosClose
call Bdos
inr a ; FFh signals failure
JRNZ FinO2 ; (wasn't that)
ABORT MsgNoClose
;
; OutFCB presently named "y:outname.$$$". Stuff in the type
; of the real output file, and erase that file. This is where,
; if the output fileref had any question marks, we could do a
; lot of damage!
;
FinO2:
lhld OutType
lda OutType+2
shld OutFCB+9
sta OutFCB+9+2
lxi d,OutFCB
mvi c,BdosOpen
call Bdos
ora a ; does the file exist?
JRNZ FinO2a ; (no, continue)
;
lhld BAKType
lda BAKType+2
shld OutFCB+9
sta OutFCB+9+2
lxi d,OutFCB
mvi c,BdosErase ; erase any .BAK file existing
call Bdos
;
lxi h,OutFCB ; move .BAK filename to new name
lxi d,OutFCB+16
lxi b,16
call MoveHtoD
lhld OutType ; put output filename in old name
lda OutType+2
shld OutFCB+9
sta OutFCB+9+2
lxi d,OutFCB
mvi c,BdosRename ; rename existing file to filename.BAK
call Bdos
inr a ; FFh means failure
JRNZ FinO2a ; (not the case)
ABORT MsgRenameEx
;
; Now set the FCB up so that it reads:
; OutFCB+0: y outname $$$
; OutFCB+16: - outname typ
; and do the rename function to rename the work file.
;
FinO2a: lxi h,OutFCB
lxi d,OutFCB+16
lxi b,16
call MoveHtoD
lhld DollarType
mov a,h
shld OutFCB+9
sta OutFCB+9+2
lxi d,OutFCB
mvi c,BdosRename
call Bdos
inr a ; FFh means failure
JRNZ FinO3 ; (not the case)
ABORT MsgRename
;
FinO3:
pop h
pop d
pop b
pop psw
ret
;
; ScanForA: scan BC bytes of HL --> text, looking for a match to
; the byte in A. Return BC and HL updated, and the Z flag true
; if a match is found or false if it is not.
; Input: HL --> text
; BC = count of bytes to scan (0000h means 65536)
; A = the byte to search for
; Preserves: A, DE
; Returns: HL incremented from 1 to BC bytes (HL points to
; the byte after the match, or to the byte after
; the scanned field if no match was found).
; BC decremented by at least 1 (BC decremented to
; zero if no match was found).
; Z flag true if a match was found.
; Note: this is the Z80 CPIR instruction. Note also that input
; of BC=0000 will cause a scan of all of storage.
;
ScanForA:
CCIR
ret
;
; The end of the program, and the start of the buffer space.
;
OBSpace equ $
;
end
;