home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d136
/
asmtoolbox
/
warlib.asm
< prev
Wrap
Assembly Source File
|
1988-03-19
|
36KB
|
1,130 lines
; WARLIB.ASM Library routines by Warren A. Ring
OpenDOSLibrary
;This routine opens the DOS liibrary
MOVEM.L D0/A1/A5-A6,-(A7) ;(Push registers)
MOVE.L A0,ScanPointer ;Set the ScanPointer and ScanCounter to scan
MOVE.L D0,ScanCounter ; the CLI line
MOVE.L _AbsExecBase,A6 ;Open the dos library
LEA.L DosName,A1
MOVEQ #0,D0 ;(Specify "any version")
JSR _LVOOpenLibrary(A6)
MOVE.L D0,DosLibraryHandle
MOVE.L DosLibraryHandle,A5 ;Save the console
JSR _LVOInput(A5) ; input handle
MOVE.L D0,ConIn ; locally
MOVE.L DosLibraryHandle,A5 ;Save the console
JSR _LVOOutput(A5) ; output handle
MOVE.L D0,ConOut ; locally
MOVEM.L (A7)+,D0/A1/A5-A6 ;(Pop registers)
RTS ;Return
DosName DC.B 'dos.library',0
CNOP 0,2
CloseDOSLibrary
;This routine closes the DOS library
MOVEM.L A1/A6,-(A7) ;(Push registers)
MOVE.L _AbsExecBase,A6 ;Close the dos
MOVE.L DosLibraryHandle,A1 ; library
JSR _LVOCloseLibrary(A6)
MOVEM.L (A7)+,A1/A6 ;(Pop registers)
RTS ;Return
OpenFile
;This routine opens an already-existing file
;In: A0 => a string buffer containing the filename
;Out: A1 => the file handle (0 = file doesn't exist)
; Zero Flag = Clear if the file exists,
; Set if the file doesn't exist
MOVEM.L D0-D3/A0/A6,-(A7) ;(Push registers)
;First, we must convert the filename from string buffer form to "C" form
ADDQ.L #4,A0 ;(Make A0 point to the current useage of
; the filename string buffer)
MOVE.L (A0)+,D1 ;Set the byte counter (D1) to the current
; useage of the string buffer
;(Make A0 point to the first data byte of
; the filename)
MOVE.L D1,D2 ;Create a temporary buffer on the stack
ADDQ.L #3,D2 ; of the length of the filename, +1, rounded
ANDI.L #$FFFE,D2 ; up to the next word boundary
SUB.L D2,A7 ;(D2 = the size of the temporary buffer on
; the stack)
MOVE.L A7,A2 ;(Make A2 point to the temporary buffer)
MOVE.L A7,A3 ;(Make A3 point to the temporary buffer)
SUBQ.L #1,D1
OpenFile2
MOVE.B (A0)+,(A2)+ ;Copy the filename from the filename string
DBRA D1,OpenFile2
MOVE.B #0,(A2)
MOVE.L A3,D1 ;Open the file
MOVEM.L A1/D2,-(A7)
MOVE.L #MODE_OLDFILE,D2
MOVE.L DosLibraryHandle,A6
JSR _LVOOpen(A6)
MOVEM.L (A7)+,A1/D2
ADD.L D2,A7 ;Delete the temporary buffer
MOVE.L D0,(A1) ;(Set the caller's file handle value)
MOVEM.L (A7)+,D0-D3/A0/A6 ;(Pop registers)
RTS ;Return
CreateFile
;This routine creates a new file
;In: A0 => a string buffer containing the filename
;Out: A1 => the file handle (0 = file could not be created)
; Zero Flag = Clear if the file was created,
; Set if the file wasn't created
;Notes: This routine deletes any already-existing file of the same name
;
; A create operation may fail because an already-existing file under
; the same name has its protection attribute set, or there is
; insufficient disk space to create the new file.
MOVEM.L D0-D3/A0/A6,-(A7) ;(Push registers)
;First, we must convert the filename from string buffer form to "C" form
ADDQ.L #4,A0 ;(Make A0 point to the current useage of
; the filename string buffer)
MOVE.L (A0)+,D1 ;Set the byte counter (D1) to the current
; useage of the string buffer
;(Make A0 point to the first data byte of
; the filename)
MOVE.L D1,D2 ;Create a temporary buffer on the stack
ADDQ.L #3,D2 ; of the length of the filename, +1, rounded
ANDI.L #$FFFE,D2 ; up to the next word boundary
SUB.L D2,A7 ;(D2 = the size of the temporary buffer on
; the stack)
MOVE.L A7,A2 ;(Make A2 point to the temporary buffer)
MOVE.L A7,A3 ;(Make A3 point to the temporary buffer)
SUBQ.L #1,D1
CreateFile2
MOVE.B (A0)+,(A2)+ ;Copy the filename from the filename string
DBRA D1,CreateFile2
MOVE.B #0,(A2)
MOVE.L A3,D1 ;Create the file
MOVEM.L A1/D2,-(A7)
MOVE.L #MODE_NEWFILE,D2
MOVE.L DosLibraryHandle,A6
JSR _LVOOpen(A6)
MOVEM.L (A7)+,A1/D2
ADD.L D2,A7 ;Delete the temporary buffer
MOVE.L D0,(A1) ;(Set the caller's file handle value)
MOVEM.L (A7)+,D0-D3/A0/A6 ;(Pop registers)
RTS ;Return
DeleteFile
;This routine deletes a file
;In: A0 => a string buffer containing the filename
;Out: D0 = the status (0 = file could not be deleted)
;Note: A delete operation may fail because the existing file has its
; protection attribute set.
MOVEM.L D0-D3/A0/A2/A3/A6,-(A7) ;(Push registers)
;First, we must convert the filename from string buffer form to "C" form
ADDQ.L #4,A0 ;(Make A0 point to the current useage of
; the filename string buffer)
MOVE.L (A0)+,D1 ;Set the byte counter (D1) to the current
; useage of the string buffer
;(Make A0 point to the first data byte of
; the filename)
MOVE.L D1,D2 ;Create a temporary buffer on the stack
ADDQ.L #3,D2 ; of the length of the filename, +1, rounded
ANDI.L #$FFFE,D2 ; up to the next word boundary
SUB.L D2,A7 ;(D2 = the size of the temporary buffer on
; the stack)
MOVE.L A7,A2 ;(Make A2 point to the temporary buffer)
MOVE.L A7,A3 ;(Make A3 point to the temporary buffer)
SUBQ.L #1,D1
DeleteFile2
MOVE.B (A0)+,(A2)+ ;Copy the filename from the filename string
DBRA D1,DeleteFile2
MOVE.B #0,(A2)
MOVE.L A3,D1 ;Delete the file
MOVEM.L A1,-(A7)
MOVE.L DosLibraryHandle,A6
JSR _LVODeleteFile(A6)
MOVEM.L (A7)+,A1
ADD.L D2,A7 ;Delete the temporary buffer
TST.L D0 ;(Set/clear the Zero Flag)
MOVEM.L (A7)+,D0-D3/A0/A2/A3/A6 ;(Pop registers)
RTS ;Return
ReadFile
;This routine reads a record from a file
;In: A0 => the file handle
; A1 => a string buffer to receive the data from the file
;Out: D0 = the number of characters read from the file
;
;Note: This routine overwrites any data already in the string buffer
MOVEM.L D1-D3/A0-A1/A5,-(A7) ;(Push registers)
MOVE.L A0,D1 ;(File specifier)
MOVE.L A1,D2 ;(Buffer location)
ADDQ.L #8,D2
MOVE.L (A1),D3 ;(# of bytes to get)
MOVEM.L A1,-(A7)
MOVE.L DosLibraryHandle,A5
JSR _LVORead(A5)
MOVEM.L (A7)+,A1
ADDQ.L #4,A1 ;Set the current useage to the number of
MOVE.L D0,(A1) ; bytes read
MOVEM.L (A7)+,D1-D3/A0-A1/A5 ;(Pop registers)
RTS ;Return
WriteFile
;This routine writes a record to a file
;In: A0 => the file handle
; A1 => a string buffer containing the data for the file
;Out: D0 = the number of characters written to the file
; (-1 = write error, possibly disk full)
MOVEM.L D1-D3/A0-A1/A5,-(A7) ;(Push registers)
MOVE.L A0,D1 ;(File specifier)
MOVE.L A1,D2 ;(Buffer location)
ADDQ.L #8,D2
ADDQ.L #4,A1
MOVE.L (A1),D3 ;(# of bytes to write)
MOVE.L DosLibraryHandle,A5
JSR _LVOWrite(A5)
MOVEM.L (A7)+,D1-D3/A0-A1/A5 ;(Pop registers)
RTS ;Return
SeekFile
;This routine moves the position in a file at which the next read or write
; is to take place.
;In: A0 => the file handle
; D0 = the offset
; D1 = the mode:
; -1 = the offset is from the beginning of the file
; 0 = the offset is from the current position in the file
; 1 = the offset is from the end of file
;Out: D0 = the previous position
; (-1 = seek error)
;
;Notes: When a file is opened, the position at which the next read or write
; is to take place is the beginning of file. This position advances
; to the byte just beyond the end of each record as that record is
; read, so that if you read a file sequentially, you need never use the
; Seek system call.
;
; If you wish to append data to the end of a file, you seek with an
; offset of zero, and a mode of 1.
MOVEM.L D1-D3/A0-A1/A5,-(A7) ;(Push registers)
MOVE.L D1,D3 ;(mode)
MOVE.L D0,D2 ;(offset)
MOVE.L A0,D1 ;(file handle)
MOVE.L DosLibraryHandle,A5
JSR _LVOSeek(A5)
MOVEM.L (A7)+,D1-D3/A0-A1/A5 ;(Pop registers)
RTS ;Return
CloseFile
;This routine closes a previously-opened file.
;In: A0 => the file handle
MOVEM.L D1/A0/A5,-(A7) ;(Push registers)
MOVE.L A0,D1
MOVE.L DosLibraryHandle,A5
JSR _LVOClose(A5)
MOVEM.L (A7)+,D1/A0/A5 ;(Pop registers)
RTS ;Return
RenameFile
;This routine renames a file
;In: A0 => a string buffer containing the current filename
; A1 => a string buffer containing the new filename
;Out: D0 = the status (0 = file could not be renamed)
;Notes: Directory names may be included in the filenames. Thus, this
; function can serve as a move function within a volume.
;
; A delete operation may fail because the destination file already
; exists, or because a named directory doesn't exist.
MOVEM.L D1-D3/D7/A0-A4/A6,-(A7);(Push registers)
MOVE.L A7,D7 ;(Save the stack pointer in D7)
;First, we must convert the source filename from SB form to "C" form
ADDQ.L #4,A0 ;(Make A0 point to the current useage of
; the filename string buffer)
MOVE.L (A0)+,D1 ;Set the byte counter (D1) to the current
; useage of the string buffer
;(Make A0 point to the first data byte of
; the filename)
MOVE.L D1,D2 ;Create a temporary buffer on the stack
ADDQ.L #3,D2 ; of the length of the filename, +1, rounded
ANDI.L #$FFFE,D2 ; up to the next word boundary
SUB.L D2,A7 ;(D2 = the size of the temporary buffer on
; the stack)
MOVE.L A7,A2 ;(Make A2 point to the temporary buffer)
MOVE.L A7,A3 ;(Make A3 point to the temporary buffer)
SUBQ.L #1,D1
RenameFile1
MOVE.B (A0)+,(A2)+ ;Copy the filename from the filename string
DBRA D1,RenameFile1
MOVE.B #0,(A2)
;Next, we must convert the destination filename from SB form to "C" form
ADDQ.L #4,A1 ;(Make A1 point to the current useage of
; the filename string buffer)
MOVE.L (A1)+,D1 ;Set the byte counter (D1) to the current
; useage of the string buffer
;(Make A1 point to the first data byte of
; the filename)
MOVE.L D1,D2 ;Create a temporary buffer on the stack
ADDQ.L #3,D2 ; of the length of the filename, +1, rounded
ANDI.L #$FFFE,D2 ; up to the next word boundary
SUB.L D2,A7 ;(D2 = the size of the temporary buffer on
; the stack)
MOVE.L A7,A2 ;(Make A2 point to the temporary buffer)
MOVE.L A7,A4 ;(Make A4 point to the temporary buffer)
SUBQ.L #1,D1
RenameFile2
MOVE.B (A1)+,(A2)+ ;Copy the filename from the filename string
DBRA D1,RenameFile2
MOVE.B #0,(A2)
;Now we rename the file
MOVE.L A3,D1 ;Rename the file
MOVE.L A4,D2
MOVE.L DosLibraryHandle,A6
JSR _LVORename(A6)
MOVE.L D7,A7 ;(Restore the stack pointer)
TST.L D0 ;(Set/clear the Zero Flag)
MOVEM.L (A7)+,D1-D3/D7/A0-A4/A6;(Pop registers)
RTS ;Return
DisplayCrlf
WritCon #DisplayCrlf_7
RTS
DisplayCrlf_7
DC.L 1,1
DC.B 10
CNOP 0,2
DisplaySpace
WritCon #DisplaySpace_7
RTS
DisplaySpace_7
DC.L 1,1
DC.B ' '
CNOP 0,2
Left_ ;BASIC Fn: B$ = Left$(A$, I)
; <A1> <A0> D0
;In: A0 => source buffer
; A1 => dest buffer
; D0 = Number of bytes to copy
MOVEM.L D0-D2/A0-A1,-(A7) ;(Push registers)
MOVE.L (A1),D2 ;(Set D2 to the max length of B$)
ADDQ.L #4,A1 ;(Make A1 point to the current useage of B$)
MOVE.L #0,(A1) ;Set the current useage of B$ to zero
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVE.L D0,D1 ;Set the byte counter (D1) to the minimum of: (1) I,
CMP.L (A0),D1 ; (2) the current useage of A$, (3) and the maximum
BLE Left_1 ; length of B$
MOVE.L (A0),D1
Left_1
CMP.L D2,D1
BLE Left_2
MOVE.L D2,D1
Left_2
TST.L D1 ;If the byte counter is 0 or negative,
BLE Left_9 ; then jump to Left_9
MOVE.L D1,(A1) ;Set the current useage of B$ to the byte counter
ADDQ.L #4,A0 ;(Make A0 point to the first data byte of A$)
ADDQ.L #4,A1 ;(Make A1 point to the first data byte of B$)
SUBI.L #1,D1 ;Copy the data bytes from A$ to B$
Left_3
MOVE.B (A0)+,(A1)+
DBRA D1,Left_3
Left_9
MOVEM.L (A7)+,D0-D2/A0-A1 ;(Pop registers)
RTS ;Return
Mid_ ;BASIC Fn: B$ = Mid$(A$, I, J)
; <A1> <A0> D0 D1
;In: A0 => source buffer
; A1 => dest buffer
; D0 = The position in A$ to start copying
; D1 = Number of bytes to copy
MOVEM.L D0-D3/A0-A1,-(A7) ;(Push registers)
MOVE.L (A1),D2 ;(Set D2 to the max length of B$)
ADDQ.L #4,A1 ;(Make A1 point to the current useage of B$)
MOVE.L #0,(A1) ;Set the current useage of B$ to zero
TST.L D0 ;If I is 0 or negative, then jump to Mid_9
BLE Mid_9
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVE.L (A0),D3 ;Set the byte counter (D3) to the minimum of: (1) J,
SUB.L D0,D3 ; (2) the current useage of A$ - I + 1, and (3) the
ADDQ.L #1,D3 ; maximum length of B$
CMP.L D1,D3
BLE Mid_1
MOVE.L D1,D3
Mid_1
CMP.L D2,D3
BLE Mid_2
MOVE.L D2,D3
Mid_2
TST.L D3 ;If the byte counter is 0 or negative,
BLE Mid_9 ; then jump to Mid_9
MOVE.L D3,(A1) ;Set the current useage of B$ to the byte counter
ADDQ.L #4,A0 ;(Make A0 point to the first data byte of A$)
ADDQ.L #4,A1 ;(Make A1 point to the first data byte of B$)
ADDA.L D0,A0 ;(Make A0 point to byte I in A$)
SUBQ.L #1,A0
SUBI.L #1,D3 ;Copy the data bytes from A$ to B$
Mid_3
MOVE.B (A0)+,(A1)+
DBRA D3,Mid_3
Mid_9
MOVEM.L (A7)+,D0-D3/A0-A1 ;(Pop registers)
RTS ;Return
Right_ ;BASIC Fn: B$ = Right$(A$, I)
; <A1> <A0> D0
;In: A0 => source buffer
; A1 => dest buffer
; D0 = The number of bytes in A$, from the right end,
; to start copying
MOVEM.L D0-D2/A0-A1,-(A7) ;(Push registers)
MOVE.L (A1),D2 ;(Set D2 to the max length of B$)
ADDQ.L #4,A1 ;(Make A1 point to the current useage of B$)
MOVE.L #0,(A1) ;Set the current useage of B$ to zero
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVE.L D0,D1 ;Set the byte counter (D1) to the minimum of: (1) I,
CMP.L (A0),D1 ; (2) the current useage of A$, (3) the max length of B$
BLE Right_1
MOVE.L (A0),D1
Right_1
CMP.L D2,D1
BLE Right_2
MOVE.L D2,D1
Right_2
TST.L D1 ;If the byte counter is 0 or negative,
BLE Right_9 ; then jump to Right_9
MOVE.L D1,(A1) ;Set the current useage of B$ to the byte counter)
MOVE.L (A0),D2 ;(Set D2 to the current length of A$)
ADDQ.L #4,A0 ;(Make A0 point to the first data byte of A$)
ADDQ.L #4,A1 ;(Make A1 point to the first data byte of B$)
SUB.L D1,D2 ;(Make A0 point to the last byte in A$, minus the
ADDA.L D2,A0 ; byte counter)
SUBQ.L #1,D1 ;Copy the data bytes from A$ to B$
Right_3
MOVE.B (A0)+,(A1)+
DBRA D1,Right_3
Right_9
MOVEM.L (A7)+,D0-D2/A0-A1 ;(Push registers)
RTS ;Return
StrCpy_ ;BASIC Fn: B$ = A$
; <A1> <A0>
;In: A0 => source buffer (A$)
; A1 => dest buffer (B$)
MOVEM.L D0,-(A7);(Push registers)
MOVE.L (A0),D0 ;Set the number of bytes to copy to the max length of A$
JSR Left_ ;Copy the data bytes from A$ to B$
MOVE.L (A7)+,D0;(Pop registers)
RTS ;Return
StrCat_ ;BASIC Fn: B$ = B$ + A$
;In: A0 => source buffer (A$)
; A1 => dest buffer (B$)
MOVEM.L D0-D2/A0-A1,-(A7) ;(Push registers)
MOVE.L (A1),D0 ;(Set D0 to the max length of B$)
ADDQ.L #4,A1 ;(Make A1 point to the current useage of B$)
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVE.L (A1),D2 ;(Set D2 to the current useage of B$)
MOVE.L (A0),D1 ;Set the byte counter (D1) to the current useage of A$
ADD.L (A1),D1 ; plus the current useage of B$
CMP.L D0,D1 ;If the byte counter > the max length of B$,
BLE StrCat_1; then set the byte counter to the max useage of B$
MOVE.L D0,D1
StrCat_1
MOVE.L D1,(A1) ;Set the current useage of B$ to the byte counter
SUB.L D2,D1 ;Subtract the current useage of B$ from the byte counter
TST.L D1 ;If the byte counter is now zero,
BEQ StrCat_9; then jump to StrCat_9
ADDQ.L #4,A0 ;(Make A0 point to the first data byte of A$)
ADDQ.L #4,A1 ;(Make A1 point to the byte after the last byte currently
ADD.L D2,A1 ; used by B$)
SUBQ.L #1,D1 ;Copy the bytes from A$ to B$
StrCat_2
MOVE.B (A0)+,(A1)+
DBRA D1,StrCat_2
StrCat_9
MOVEM.L (A7)+,D0-D2/A0-A1 ;(Pop registers)
RTS ;Return
StrCmp_ ;C fn: I = (A$==B$);
;This routine indicates whether or not A$ = B$
;In: A0 => source buffer (A$)
; A1 => dest buffer (B$)
;Out: <Zero flag> = Set if the strings are equal,
; = Clear if the strings are unequal
MOVEM.L D0/A0-A1,-(A7) ;(Push registers)
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
ADDQ.L #4,A1 ;(Make A1 point to the current useage of B$)
MOVE.L (A0),D0 ;Set the byte counter (D0) to the current useage of A$
CMPM.L (A0)+,(A1)+;If the current useage of A$ <> the current useage
BNE StrCmp_9; of B$, then jump to StrCmp_9
SUBQ.L #1,D0 ;If the A$ data bytes <> the B$ data bytes,
StrCmp_5 ; then jump to StrCmp_9
CMPM.B (A0)+,(A1)+
BNE StrCmp_9
DBRA D0,StrCmp_5
ORI #$4,CCR ;Set the zero flag
StrCmp_9
MOVEM.L (A7)+,D0/A0-A1 ;(Pop registers)
RTS ;Return
StrLen_ ;BASIC Fn: I = LEN(A$)
;This routine indicates the current length of a string
;In: A0 => the buffer (A$)
;Out: D0 = the current useage of A$
MOVEM.L A0,-(A7) ;(Push registers)
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVE.L (A0),D0 ;Set D0 to the current useage of A$
MOVEM.L (A7)+,A0 ;(Pop registers)
RTS ;Return
Scanw_
;This routine scans a string for the next visible word
;In: ScanPointer => the next byte in the string to be scanned
; ScanCounter = the number of bytes in the string remaining
; to be scanned
; A0 => the dest buffer
;Out: ScanPointer, ScanCounter are updated
;
;Note: This routine skips over spaces, tabs, and other invisible characters
MOVEM.L D0-D2/A0-A2,-(A7) ;(Push registers)
MOVE.L (A0)+,D1;(Set D1 to the max length of A$)
MOVE.L A0,A1 ;(Make A1 point to the current length of A$)
MOVE.L #0,(A1) ;Set the current useage of A$ to 0
ADDQ.L #4,A0 ;Advance the dest buffer pointer (A0) to the first data
; byte of A$
MOVE.L ScanPointer,A2;(Set A1 to the scan pointer)
MOVE.L ScanCounter,D2;If the scan counter (D2) is zero,
BEQ Scanw_9 ; then jump to Scanw_9
Scanw_1
MOVE.B (A2)+,D0;Fetch the character at which the scan pointer points,
; and advance the scan pointer
SUBQ.L #1,D2 ;Decrement the scan counter
CMPI.B #'!',D0 ;If the character is visible, then jump to Scanw_2
BLT Scanw_3
CMPI.B #$7F,D0
BLT Scanw_2
Scanw_3
TST.L D2 ;If the scan counter is zero, then jump to Scanw_9
BEQ Scanw_9
BRA Scanw_1 ;Jump to Scanw_1
Scanw_2
MOVE.B D0,(A0)+;Place the character into A$,
; and advance the dest buffer pointer
ADD.L #1,(A1) ;Increment the current useage of A$
CMP.L (A1),D1 ;If the current useage of A$ = the max length of A$,
BEQ Scanw_9 ; then jump to Scanw_9
TST.L D2 ;If the scan counter is zero, then jump to Scanw_9
BEQ Scanw_9
MOVE.B (A2)+,D0;Fetch the character at which the scan pointer points,
; and advance the scan pointer
SUBQ.L #1,D2 ;Decrement the scan counter
CMPI.B #'!',D0 ; If the character is visible, then jump to Scanw_2
BCC Scanw_2
Scanw_9
MOVE.L A2,ScanPointer;(Update the scan pointer)
MOVE.L D2,ScanCounter;(Update the scan counter)
MOVEM.L (A7)+,D0-D2/A0-A2 ;(Pop registers)
RTS ;Return
Scana_
;This routine scans a string for the next alphanumeric word
;In: ScanPointer => the next byte in the string to be scanned
; ScanCounter = the number of bytes in the string remaining
; to be scanned
; A0 => the dest buffer
;Out: ScanPointer, ScanCounter are updated
;
;Note: This routine skips over spaces, tabs, and invisible characters
; including non-alphanumeric characters
MOVEM.L D0-D2/A0-A2,-(A7) ;(Push registers)
MOVE.L (A0)+,D1;(Set D1 to the max length of A$)
MOVE.L A0,A1 ;(Make A1 point to the current length of A$)
MOVE.L #0,(A1) ;Set the current useage of A$ to 0
ADDQ.L #4,A0 ;Advance the dest buffer pointer (A0) to the first data
; byte of A$
MOVE.L ScanPointer,A2;(Set A1 to the scan pointer)
MOVE.L ScanCounter,D2;If the scan counter (D2) is zero,
BEQ Scana_9 ; then jump to Scana_9
Scana_1
MOVE.B (A2)+,D0;Fetch the character at which the scan pointer points,
; and advance the scan pointer
SUBQ.L #1,D2 ;Decrement the scan counter
CMPI.B #$30,D0 ;If the character is alphanumeric, then jump to Scana_2
BLT Scana_3
CMPI.B #$3A,D0
BLT Scana_2
CMPI.B #$41,D0
BLT Scana_3
CMPI.B #$5B,D0
BLT Scana_2
CMPI.B #$61,D0
BLT Scana_3
CMPI.B #$7B,D0
BLT Scana_2
Scana_3
TST.L D2 ;If the scan counter is zero, then jump to Scana_9
BEQ Scana_9
BRA Scana_1 ;Jump to Scana_1
Scana_2
MOVE.B D0,(A0)+;Place the character into A$,
; and advance the dest buffer pointer
ADD.L #1,(A1) ;Increment the current useage of A$
CMP.L (A1),D1 ;If the current useage of A$ = the max length of A$,
BEQ Scana_9 ; then jump to Scana_9
TST.L D2 ;If the scan counter is zero, then jump to Scana_9
BEQ Scana_9
MOVE.B (A2)+,D0;Fetch the character at which the scan pointer points,
; and advance the scan pointer
SUBQ.L #1,D2 ;Decrement the scan counter
CMPI.B #$30,D0 ; If the character is alphanumeric, then jump to Scana_2
BLT Scana_4
CMPI.B #$3A,D0
BLT Scana_2
CMPI.B #$41,D0
BLT Scana_4
CMPI.B #$5B,D0
BLT Scana_2
CMPI.B #$61,D0
BLT Scana_4
CMPI.B #$7B,D0
BLT Scana_2
Scana_4
Scana_9
MOVE.L A2,ScanPointer;(Update the scan pointer)
MOVE.L D2,ScanCounter;(Update the scan counter)
MOVEM.L (A7)+,D0-D2/A0-A2 ;(Pop registers)
RTS ;Return
Scanc_
;This routine scans a string for the next character
;In: ScanPointer => the next byte in the string to be scanned
; ScanCounter = the number of bytes in the string remaining
; to be scanned
; A0 => the dest buffer
;Out: ScanPointer, ScanCounter are updated
;
MOVEM.L D0-D2/A0-A2,-(A7) ;(Push registers)
MOVEQ.L #0,D0 ;Set the byte counter to 0
ADDQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVEA.L ScanPointer,A1;(Set A1 to the scan pointer)
MOVE.L ScanCounter,D1;(Set D1 to the scan counter)
BEQ Scanc_9 ;If the scan counter is 0, then jump to Scanc_9
MOVE.B (A1)+,D2;Fetch the character at which the scan pointer points,
; and advance the scan pointer
SUBQ.L #1,D1 ;Decrement the scan counter
ADDQ.L #4,A0 ;(Make A0 point to the first data byte in A$)
MOVE.B D2,(A0) ;Place the character in the buffer
SUBQ.L #4,A0 ;(Make A0 point to the current useage of A$)
MOVEQ.L #1,D0 ;Set the byte counter to 1
Scanc_9
MOVE.L D0,(A0) ;Set the current useage in A$ to the byte counter
MOVE.L A1,ScanPointer;(Update the scan pointer)
MOVE.L D1,ScanCounter;(Update the scan counter)
MOVEM.L (A7)+,D0-D2/A0-A2 ;(Pop registers)
RTS ;Return
ItoA_ ;BASIC Fn: A$ = STR$(I)
; (A0) (D0)
;This routine converts a signed integer from binary to a decimal ASCII
; string
MOVEM.L D0-D4/A0-A4,-(A7) ;(Push registers)
MOVE.L #ItoA_values,A1;Set the table pointer (A1) to the beginning of
; the table
MOVEQ.L #10,D1 ;Set the table counter (D1) to the length of the table
MOVEQ.L #0,D4 ;Set the character counter (D4) to 0
MOVE.L (A0)+,D2;Set the limit value (D2) to the max length of A$
MOVE.L A0,A2 ;(Make A2 point to the current useage of A$)
ADDQ.L #4,A0 ;(Make A0 and A4 point to the first data byte in A$)
MOVE.L A0,A4
TST.L D0 ;If I >= 0, then jump to ItoA_1
BPL ItoA_1
MOVE.B #'-',(A0)+;Place a '-' in A$, and advance the A$ pointer
ADDQ.L #1,D4 ;Increment the character counter
CMP.L D2,D4 ;If the character counter equals the limit value,
BEQ ItoA_5 ; then jump to ItoA_5
NEG.L D0 ;Complement I
ItoA_1
CMP.L (A1),D0 ;If I >= the table value,
BCC ItoA_2 ; then jump to ItoA_2
ADDQ.L #4,A1 ;Advance the table pointer
SUBQ.L #1,D1 ;Decrement the table counter
CMPI.L #1,D1 ;If the table counter is not yet 1,
BNE ItoA_1 ; then jump to ItoA_1
ItoA_2
MOVE.B #'0',(A0);Set the character to '0'
ADDQ.L #1,D4 ;Increment the character counter
ItoA_3
SUB.L (A1),D0 ;Subtract the table value from I
BCS ItoA_4 ;If I is negative, then jump to ItoA_4
ADDQ.B #1,(A0) ;Increment the data byte in A$
BRA ItoA_3 ;Jump to ItoA_3
ItoA_4
ADD.L (A1),D0 ;Add the table value to I, making I positive again
ADDQ.L #4,A1 ;Advance the table pointer to the next value
SUBQ.L #1,D1 ;Decrement the table counter
BEQ ItoA_7 ;If the table counter is zero, then jump to ItoA_7
ADDQ.L #1,A0 ;Advance the A$ pointer
CMP.L D4,D2 ;If the character counter <= the limit value,
BGT ItoA_2 ; then jump to ItoA_2
ItoA_5
MOVE.L D2,(A2) ;Set the current useage of A$ to the max length of A$
SUBQ.L #1,D4 ;Fill the buffer with astericks
ItoA_6
MOVE.B #'*',(A4)+
DBRA D4,ItoA_6
BRA ItoA_8 ;Jump to Itoa_8
ItoA_7
MOVE.L D4,(A2) ;Set the current useage of A$ to the character count
ItoA_8
MOVEM.L (A7)+,D0-D4/A0-A4 ;(Pop registers)
RTS ;Return
ItoA_values
DC.L 1000000000
DC.L 100000000
DC.L 10000000
DC.L 1000000
DC.L 100000
DC.L 10000
DC.L 1000
DC.L 100
DC.L 10
DC.L 1
AtoI_ ;BASIC Fn: I = VAL(A$)
; (D0) (A0)
;This routine converts a decimal ASCII string to a signed binary integer
MOVEM.L D1-D4/A0-A1,-(A7) ;(Push registers)
MOVEQ.L #0,D0 ;Set the character field to zero
MOVEQ.L #0,D2 ;Set the result (D2) to 0
MOVEQ.L #0,D3 ;Clear the negative flag (D3)
ADDQ.L #4,A0 ;(Make A1 point to the current useage of A$)
MOVE.L A0,A1
MOVE.L (A0)+,D1;Set the byte counter (D1) to the current useage of A$
;(Make A0 point to the first data byte in A$)
BEQ AtoI_9 ;If the byte counter is zero, then jump to AtoI_9
MOVE.B (A0)+,D0;Fetch the first data byte in A$
;(Make A0 point to the second data byte in A$)
CMPI.B #'-',D0 ;If the byte is not a '-', then jump to AtoI_1
BNE AtoI_1
MOVEQ.L #1,D3 ;Set the negative flag
BRA AtoI_4 ;Jump to AtoI_4
AtoI_1
CMPI.B #'0',D0 ;If the byte is not numeric, then jump to AtoI_9
BLT AtoI_9
CMPI.B #'9',D0
BGT AtoI_9
LSL.L #1,D2 ;Multiply the result by 10
MOVE.L D2,D4
LSL.L #2,D2
ADD.L D4,D2
SUBI.B #'0',D0 ;Convert the byte to binary
ADD.L D0,D2 ;Add the byte to the result
AtoI_4
SUBQ.L #1,D1 ;Decrement the byte counter
BEQ AtoI_9 ;If the byte counter is zero, then jump to AtoI_9
MOVE.B (A0)+,D0;Fetch the next data byte in A$
;(Make A0 point to the next data byte in A$)
BRA AtoI_1 ;Jump to AtoI_1
AtoI_9
TST.L D3 ;If the negative flag is clear, then jump to AtoI_A
BEQ AtoI_A
NEG.L D2 ;Negate the result
AtoI_A
MOVE.L D2,D0 ;Set D0 to the result
MOVEM.L (A7)+,D1-D4/A0-A1 ;(Pop registers)
RTS ;Return
HAtoI_ ;BASIC Fn: I = HEX(A$)
; (D0) (A0)
;This routine converts a hex-ASCII string to a binary integer
;
;Note: Conversion stops if a non-hex-ASCII character is encountered in
; the string
MOVEM.L D1-D2,-(A7) ;(Push registers)
MOVEQ.L #0,D2 ;Set the result (D2) to 0
ADDQ.L #4,A0 ;Set the limit value (D1) to the current length of A$
MOVE.L (A0)+,D1;(Make A0 point to the current useage of A$)
HAtoI_1
MOVE.B (A0)+,D0;If the first (next) character in A$ is not a hex-ASCII
JSR IsHexASCII; character, then jump to HAtoI_7
BEQ HAtoI_7
CMPI.B #'9'+1,D0;Convert the hex-ASCII character to a binary value
BCS HAtoI_2
ANDI.B #$0F,D0
ADD.L #9,D0
BRA HAtoI_3
HAtoI_2
SUB.L #'0',D0
HAtoI_3
LSL.L #4,D2 ;Shift the result left 4 bits
OR.L D0,D2 ;'Or' the binary value into the result
SUBQ.L #1,D1 ;Decrement the limit value
BNE HAtoI_1 ;If the limit value is not yet zero,
; then jump to HAtoI_1
HAtoI_7
MOVE.L D2,D0 ;(Set D0 to the result)
MOVEM.L (A7)+,D1-D2 ;(Pop registers)
RTS ;Return
ItoHA8_ ;BASIC Fn: A$ = STR8HEX$(I)
; (A0) (D0)
MOVEM.L D1,-(A7);(Push registers)
MOVEQ.L #8,D1 ;Set the field width to 8
JSR ItoHA_ ;Convert the field
MOVEM.L (A7)+,D1;(Pop registers)
RTS ;Return
ItoHA4_ ;BASIC Fn: A$ = STR4HEX$(I)
; (A0) (D0)
MOVEM.L D1,-(A7);(Push registers)
MOVEQ.L #4,D1 ;Set the field width to 4
JSR ItoHA_ ;Convert the field
MOVEM.L (A7)+,D1;(Pop registers)
RTS ;Return
ItoHA2_ ;BASIC Fn: A$ = STR2HEX$(I)
; (A0) (D0)
MOVEM.L D1,-(A7);(Push registers)
MOVEQ.L #2,D1 ;Set the field width to 2
JSR ItoHA_ ;Convert the field
MOVEM.L (A7)+,D1;(Pop registers)
RTS ;Return
ItoHA1_ ;BASIC Fn: A$ = STR1HEX$(I)
; (A0) (D0)
MOVEM.L D1,-(A7);(Push registers)
MOVEQ.L #1,D1 ;Set the field width to 1
JSR ItoHA_ ;Convert the field
MOVEM.L (A7)+,D1;(Pop registers)
RTS ;Return
ItoHA_ ;BASIC Fn: A$ = STRHEX$(I)
; (A0) (D0)
;In: D1 = the number of hex-ASCII characters to convert
MOVEM.L D0-D5,-(A7) ;(Push registers)
MOVE.L D1,D2 ;(Set D2 to the field width -1)
SUBQ.L #1,D2
MOVE.L (A0)+,D3;If the max length of A$ < the field width,
CMP.L D1,D3 ; (Make A0 point to the current useage of A$)
BLT ItoHA_7 ; then jump to ItoHA_7
; (Set D3 to the max length of A$)
MOVE.L D1,(A0)+;Set the current useage of A$ to the field width
;(Make A0 point to the first data byte of A$)
CMPI.L #1,D1 ;If the field width is 1,
BEQ ItoHA_2 ; then jump to ItoHA_2
MOVE.L D2,D4 ;Rotate I right by the field width -1 times 4 bits
SUBQ.L #1,D4
ItoHA_1
ROR.L #4,D0
DBRA D4,ItoHA_1
ItoHA_2
MOVE.L D2,D4 ;Set the counter to the field width -1
ItoHA_3
MOVE.B D0,D5 ;Convert I bits 3-0 to a hex-ASCII character
AND.L #$0F,D5
ADD.L #'0',D5
CMP.L #'9'+1,D5
BLT ItoHA_4
ADDQ.L #7,D5
ItoHA_4
MOVE.B D5,(A0)+;Place the character in A$
;(Make A0 point to the next data byte in A$)
ROL.L #4,D0 ;Rotate I left by 4 bits
DBRA D4,ItoHA_3;Decrement the counter
;If the counter is not yet -1, then jump to ItoHA_2
BRA ItoHA_9 ;Jump to ItoHA_9
ItoHA_7
MOVE.L D3,(A0)+;Set the current useage of A$ to the max length of A$
SUBQ.L #1,D3 ;Fill A$ with astericks
ItoHA_8
MOVE.B #'*',(A0)+
DBRA D3,ItoHA_8
ItoHA_9
MOVEM.L (A7)+,D0-D5 ;(Pop registers)
RTS ;Return
IsHexASCII ;Is hex-ASCII routine
;This routine determines whether or not a character
; is a valid hex-ASCII character
;In: <D0.B> = the character
;Out: <Zero> = Clear if the character is a hex-ASCII
; character,
; = Set if the character is not a hex-
; ASCII character
MOVE.L D0,-(A7) ;Push registers
ANDI.L #$FF,D0 ;Strip off all but bits 7-0
CMPI.B #'0',D0 ;If the character is not a hex-ASCII character,
BMI IsHex8 ; then jump to IsHex8
CMPI.B #'9'+1,D0 ;If in the range "0" - "9", then jump to IsHex4
BMI IsHex4
CMPI.B #'A',D0
BMI IsHex8
CMPI.B #'F'+1,D0 ;If in the range "A" - "F", then jump to IF#4
BMI IsHex4
CMPI.B #'a',D0
BMI IsHex8
CMPI.B #'f'+1,D0 ;If in the range "0" - "f", then jump to IsHex4
BMI IsHex4
BRA IsHex8 ;Jump to IsHex8
IsHex4
MOVE.L (A7)+,D0 ;Pop registers
ANDI #$FB,CCR ;Clear the zero flag
BRA IsHex9
IsHex8
MOVE.L (A7)+,D0 ;Pop registers
ORI #$04,CCR ;Set the zero flag
IsHex9
RTS ;Return
IFND ScanPointer
ScanPointer
DS.L 1
ENDC
IFND ScanCounter
ScanCounter
DS.L 1
ENDC
IFND ConIn
ConIn
DS.L 1
ENDC
IFND ConOut
ConOut
DS.L 1
ENDC
IFND DosLibraryHandle
DosLibraryHandle
DS.L 1
ENDC
IFND SystemSP
SystemSP
DS.L 1
ENDC
IFND MODE_OLDFILE
MODE_OLDFILE EQU 1005
ENDC
IFND MODE_NEWFILE
MODE_NEWFILE EQU 1006
ENDC