home *** CD-ROM | disk | FTP | other *** search
- ;
- ; 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
- ;