mirror of
https://github.com/marketideas/qasm.git
synced 2026-10-25 13:02:45 +00:00
Move the assembler to src/qasm. qlink links OMF 1.0 and 2.0 from a script. makeBin flattens a load file, qomf dumps OMF, and qpro builds ProDOS volumes. APW and MPW assemble through the ORCA front end. Relocatable modules emit OMF objects. Listings stay off unless -l is set. make boot assembles the GS/OS 6.0.1 ProDOS 8 kernel and BASIC.SYSTEM into an 800K volume. BASIC.SYSTEM accepts ls and pfx, and its splash reports PRODOS BASIC 2.0, copyright 1983-2026. IIGS.601.SRC is the source and the BASIC.SYSTEM oracle that image is built from.
1 line
21 KiB
Plaintext
1 line
21 KiB
Plaintext
TITLE ', FILES.a - Next_Header'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Read Next Segment Header
|
|
*
|
|
* Inputs: Header_Mark - Segment Header File Mark
|
|
*
|
|
* Outputs: A - status
|
|
* C - set if error occurred
|
|
* Header - contains Segment Header
|
|
* Header_Mark - File Mark of next Segment Header
|
|
*
|
|
* Zero Page used: TempZero
|
|
*
|
|
****************************************************************
|
|
*
|
|
Next_Header PROC
|
|
with DirectPage, Globals
|
|
;
|
|
; is Header_Mark in current File Buffer ?
|
|
;
|
|
lda |Header_Mark
|
|
sec
|
|
sbc |File_Mark
|
|
sta TempZero
|
|
lda |Header_Mark+2
|
|
sbc |File_Mark+2
|
|
sta TempZero+2
|
|
bne cont1
|
|
lda TempZero
|
|
cmp |File_EOB
|
|
bcs cont1
|
|
;
|
|
; yes, set File_Pt to location of Header_Mark
|
|
;
|
|
sta |File_Pt
|
|
bra cont2
|
|
;
|
|
; no, is this is a Memory Load
|
|
;
|
|
cont1 lda Memory_Load
|
|
beq cont1a
|
|
;
|
|
; yes, set EOF condition and exit
|
|
;
|
|
lda #eofEncountered
|
|
error_skip
|
|
jmp error
|
|
;
|
|
; no, set Mark of file to Header_Mark
|
|
;
|
|
cont1a lda |Header_Mark
|
|
sta |PSetMark.position
|
|
lda |Header_Mark+2
|
|
sta |PSetMark.position+2
|
|
|
|
jsl $E100A8 ;call GS/OS
|
|
dc.w SET_MARK
|
|
dc.l PSetMark
|
|
bcs error_skip
|
|
;
|
|
; fill File Buffer
|
|
;
|
|
jsr Fill_File_Buff
|
|
bcs error_skip
|
|
;
|
|
; read 1st part of Header (up to DispData) so that size of
|
|
; complete Header can be determined
|
|
;
|
|
cont2 pea Header>>16 ;Address
|
|
pea |Header
|
|
pea SegmentHeader.DispData+2>>16 ;Bytes
|
|
pea SegmentHeader.DispData+2
|
|
jsr Read_File
|
|
lda #NotLoad ;error means garbage header
|
|
bcs error_skip
|
|
;
|
|
; allocate a buffer for rest of Header
|
|
;
|
|
lda Header.DispData
|
|
sec
|
|
sbc #SegmentHeader.DispData+2
|
|
sta TempZero ;calculate size
|
|
tax
|
|
ldy #0 ;high word of size
|
|
lda #uFileBuff ;user ID to use
|
|
jsr do_alloc ;allocate the memory
|
|
bcs error_skip
|
|
txa
|
|
jsr DeRef ;dereference Handle
|
|
sta |Header_Var ;save Pointer in Globals
|
|
sty |Header_Var+2
|
|
|
|
;
|
|
; read 2nd part of Header
|
|
;
|
|
cont3 phy ;Address
|
|
pha
|
|
pea 0
|
|
pei TempZero ;Bytes
|
|
jsr Read_File
|
|
lda #NotLoad ;error means garbage header
|
|
bcs error
|
|
;
|
|
; change DISPNAME to the offset of SEGNAME in Header_Var (for convenience in finding
|
|
; the Segment Name)
|
|
;
|
|
lda Header.DispName
|
|
sec
|
|
sbc #SegmentHeader.DispData+2-10
|
|
sta Header.DispName
|
|
;
|
|
; bump Header_Mark to next Header
|
|
;
|
|
jsr Bump_Mark
|
|
;
|
|
; check KIND fields (in case old KIND field was used)
|
|
;
|
|
jsr Check_KIND
|
|
|
|
return lda #0
|
|
error cmp #eofEncountered ;End of File encountered
|
|
beq error1
|
|
cmp #outOfRange ;Position out of range
|
|
bne error2
|
|
error1 lda #NoFind ;either error is a No Find error
|
|
error2 cmp #1
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Read_File'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Read File from File Buffer
|
|
*
|
|
* Inputs: Address of User Buffer (TOS+7)
|
|
* Bytes to read (TOS+3)
|
|
*
|
|
* Outputs: A - status
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: TempZero
|
|
*
|
|
* If address is zero, file will be positioned but
|
|
* no data will be transferred
|
|
*
|
|
****************************************************************
|
|
*
|
|
Read_File PROC
|
|
with DirectPage, Globals
|
|
|
|
Address equ 7
|
|
Bytes equ 3
|
|
;
|
|
; is Bytes<$10000 and File_Pt+Bytes<$10000 and File_Pt+Bytes<=File_EOB ?
|
|
;
|
|
lda Bytes+2,s ;if high byte of Bytes not 0,
|
|
bne cont3 ; Bytes>$10000
|
|
lda |File_Pt
|
|
clc
|
|
adc Bytes,s
|
|
bcs cont3 ;if carry set, File_Pt+Bytes>$10000
|
|
cmp |File_EOB
|
|
beq cont1
|
|
bcs cont3
|
|
;
|
|
; yes, do actual read
|
|
;
|
|
cont1 lda Bytes,s
|
|
pha
|
|
jsr Actual_Read
|
|
pla ;remove bytes
|
|
lda #0 ;no errors
|
|
bra return ;done
|
|
;
|
|
; no, read File_EOB-File_Pt bytes to user's buffer
|
|
;
|
|
cont3 lda |File_EOB
|
|
sec
|
|
sbc |File_Pt
|
|
pha
|
|
jsr Actual_Read
|
|
;
|
|
; if Address<>0, increment Address by partial Bytes
|
|
;
|
|
lda Address+2,s
|
|
ora Address+4,s
|
|
beq cont4
|
|
lda 1,s
|
|
clc
|
|
adc Address+2,s
|
|
sta Address+2,s
|
|
lda Address+4,s
|
|
adc #0
|
|
sta Address+4,s
|
|
;
|
|
; decrement Bytes by partial Bytes
|
|
;
|
|
cont4 lda Bytes+2,s
|
|
sec
|
|
sbc 1,s
|
|
sta Bytes+2,s
|
|
lda Bytes+4,s
|
|
sbc #0
|
|
sta Bytes+4,s
|
|
pla ;remove partial Bytes from stack
|
|
;
|
|
; refill File Buffer
|
|
;
|
|
jsr Fill_File_Buff
|
|
bcs error
|
|
;
|
|
; if there are still bytes to read, loop
|
|
;
|
|
lda Bytes,s
|
|
ora Bytes+2,s
|
|
bne Read_File
|
|
|
|
return
|
|
error Stack_Cleanup 8
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Actual_Read'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Actual Read from File Buffer
|
|
*
|
|
* Inputs: Address of User Buffer (TOS+12)
|
|
* Bytes to read (TOS+3)
|
|
*
|
|
* Outputs: none
|
|
*
|
|
* Zero Page used: TempZero
|
|
*
|
|
* If address is zero, file will be positioned but
|
|
* no data will be transferred
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Actual_Read PROC
|
|
with DirectPage, Globals
|
|
|
|
Address equ 11
|
|
Bytes equ 3
|
|
;
|
|
; threshold at which the Block Move routine is used rather
|
|
; than the internal move loop
|
|
;
|
|
Size_Threshold equ 64
|
|
;
|
|
; if address=0, don't move any data
|
|
;
|
|
lda Address,s
|
|
ora Address+2,s
|
|
beq cont2
|
|
;
|
|
; calculate address of next byte in File Buffer = File_Buff+File_Pt
|
|
;
|
|
lda |File_Buff
|
|
clc
|
|
adc |File_Pt
|
|
sta TempZero
|
|
lda |File_Buff+2
|
|
adc #0
|
|
sta TempZero+2
|
|
;
|
|
; check whether Bytes to read < Size_Threshold
|
|
;
|
|
lda Bytes,s
|
|
cmp #Size_Threshold
|
|
bcs cont1b
|
|
;
|
|
; yes, use simple load-store loop
|
|
;
|
|
tay
|
|
lda Address,s
|
|
sta TempZero+4
|
|
lda Address+2,s
|
|
sta TempZero+6
|
|
sep #$30
|
|
longa on
|
|
longi on
|
|
loop dey
|
|
bmi cont1a
|
|
lda [TempZero],y
|
|
sta [TempZero+4],y
|
|
bra loop
|
|
cont1a rep #$30
|
|
longa on
|
|
longi on
|
|
bra cont2
|
|
;
|
|
; no, use Block Move
|
|
;
|
|
cont1b pei TempZero+2 ;Source
|
|
pei TempZero
|
|
lda Address+6,s ;Destination
|
|
pha
|
|
lda Address+6,s
|
|
pha
|
|
pea 0
|
|
lda Bytes+10,s ;Count
|
|
pha
|
|
jsr Block_Move
|
|
;
|
|
; bump File_Pt by Bytes
|
|
;
|
|
cont2 lda Bytes,s
|
|
clc
|
|
adc |File_Pt
|
|
sta |File_Pt
|
|
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Read_Op'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Read next OP code from File Buffer
|
|
*
|
|
* Inputs: none
|
|
*
|
|
* Outputs: Record - updated with Op Code
|
|
* A - status if error
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Read_Op PROC
|
|
with DirectPage, Globals
|
|
;
|
|
; save File Mark corresponding to this OP code
|
|
;
|
|
lda |File_Pt
|
|
tay ;save
|
|
clc
|
|
adc |File_Mark
|
|
sta Op_Mark
|
|
lda #0
|
|
adc |File_Mark+2
|
|
sta Op_Mark+2
|
|
;
|
|
; if File Pointer is at very end of File Buffer, use
|
|
; Read_File routine instead
|
|
;
|
|
cpy |File_EOB
|
|
bne cont
|
|
pea Record>>16
|
|
pea |Record
|
|
pea 0
|
|
pea 1
|
|
jsr Read_File
|
|
rts
|
|
;
|
|
; move 1 byte into Record
|
|
;
|
|
cont lda [FileBuff],y
|
|
sta |Record
|
|
;
|
|
; bump File_Pt
|
|
;
|
|
inc |File_Pt
|
|
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Read_Record'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Read next record from File Buffer
|
|
*
|
|
* Inputs: X - # of bytes
|
|
*
|
|
* Outputs: Record - updated
|
|
* A - status if error
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Read_Record PROC
|
|
with DirectPage, Globals
|
|
|
|
pea Record>>16
|
|
pea |Record
|
|
pea 0
|
|
phx
|
|
jsr Read_File
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Skip_Header'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Skip Next Segment Header
|
|
*
|
|
* Inputs: Header_Mark - Segment Header File Mark
|
|
*
|
|
* Outputs: A - status
|
|
* C - set if error occurred
|
|
* Header_Mark - File Mark of next Segment Header
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Skip_Header PROC
|
|
with DirectPage, Globals
|
|
;
|
|
; set Mark of file to input Mark
|
|
;
|
|
lda |Header_Mark
|
|
sta |PSetMark.position
|
|
lda |Header_Mark+2
|
|
sta |PSetMark.position+2
|
|
|
|
jsl $E100A8 ;call GS/OS
|
|
dc.w SET_MARK
|
|
dc.l PSetMark
|
|
bcs error
|
|
;
|
|
; read part of next Segment Header (enough to see BYTECNT and VERSION)
|
|
;
|
|
lda #<Header
|
|
sta |PRead.dataBuffer ;set read address
|
|
lda #^Header
|
|
sta |PRead.dataBuffer+2
|
|
lda #SegmentHeader.Kind+1
|
|
sta |PRead.requestCount ;read enough bytes
|
|
lda #^SegmentHeader.Kind+1
|
|
sta |PRead.requestCount+2
|
|
|
|
jsl $E100A8
|
|
dc.w PD_READ
|
|
dc.l PRead
|
|
bcs error
|
|
;
|
|
; bump Header_Mark to next Header
|
|
;
|
|
cont jsr Bump_Mark
|
|
|
|
return lda #0
|
|
clc
|
|
error rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Next_Dictionary'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Position File to Relocation Dictionary of current Segment
|
|
*
|
|
* Inputs: Current offset into Mark List (TOS+3)
|
|
*
|
|
* Outputs: Next offset into Mark List (TOS+7)
|
|
* CSegNum - Segment Number in Mark List
|
|
* - 0 if no more entries
|
|
* A - status
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: TempZero
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Next_Dictionary PROC
|
|
with DirectPage, Globals
|
|
|
|
IOffset equ 3 ;input Offset
|
|
OOffset equ 7 ;output Offset
|
|
;
|
|
; if input Offset points to last entry in Mark List,
|
|
; set CSegNum to 0 and return
|
|
;
|
|
; last entry if output offset = Next Available Slot
|
|
;
|
|
stz CSegNum
|
|
lda IOffset,s
|
|
cmp [MarkList]
|
|
bne cont1
|
|
lda IOffset+2,s
|
|
ldy #2
|
|
cmp [MarkList],y
|
|
beq return
|
|
;
|
|
; calculate address of entry in Mark List
|
|
;
|
|
cont1 lda IOffset,s
|
|
clc
|
|
adc MarkList
|
|
sta TempZero
|
|
lda IOffset+2,s
|
|
adc MarkList+2
|
|
sta TempZero+2
|
|
;
|
|
; extract Mark and store in ProDOS SetMark packet
|
|
;
|
|
ldy #2
|
|
lda [TempZero],y
|
|
sta |PSetMark.position
|
|
ldy #4
|
|
lda [TempZero],y
|
|
sta |PSetMark.position+2
|
|
;
|
|
; is Mark in current File Buffer ?
|
|
;
|
|
lda |PSetMark.position
|
|
sec
|
|
sbc |File_Mark
|
|
sta TempZero+4
|
|
lda |PSetMark.position+2
|
|
sbc |File_Mark+2
|
|
sta TempZero+6
|
|
bne cont2
|
|
lda TempZero+4
|
|
cmp |File_EOB
|
|
bcs cont2
|
|
;
|
|
; yes, set File_Pt to location in File Buffer where Mark is
|
|
;
|
|
sta |File_Pt
|
|
bra cont3
|
|
;
|
|
; no, set File Mark
|
|
;
|
|
cont2 jsl $E100A8 ;call GS/OS
|
|
dc.w SET_MARK
|
|
dc.l PSetMark
|
|
bcs error
|
|
;
|
|
; fill File Buffer
|
|
;
|
|
jsr Fill_File_Buff
|
|
bcs error
|
|
;
|
|
; set output offset = input offset + ML_SizeEntry
|
|
;
|
|
cont3 lda IOffset,s
|
|
clc
|
|
adc #ML_SizeEntry
|
|
sta OOffset,s
|
|
lda IOffset+2,s
|
|
adc #0
|
|
sta OOffset+2,s
|
|
;
|
|
; set CSegNum to SegNum in entry
|
|
;
|
|
lda [TempZero]
|
|
sta CSegNum
|
|
|
|
return lda #0
|
|
error Stack_Cleanup 4
|
|
rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Setup_Buf_Ptrs'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Setup buffer pointers
|
|
*
|
|
****************************************************************
|
|
*
|
|
Setup_Buf_Ptrs Proc
|
|
with DirectPage, Globals
|
|
|
|
Entry zero_marks
|
|
;
|
|
; check amount of memory on system
|
|
;
|
|
pha
|
|
pha
|
|
_TotalMem
|
|
pla
|
|
plx
|
|
;
|
|
; if a minimal system (512K), use an 8K buffer, otherwise use 16K
|
|
;
|
|
lda #$4000
|
|
cpx #8
|
|
bne @cont1
|
|
lda #$2000
|
|
;
|
|
; set File Buffer size
|
|
;
|
|
@cont1 sta |File_Buff_Size
|
|
;
|
|
; allocate a File Buffer
|
|
;
|
|
ldx #0
|
|
phx ;output Handle
|
|
phx
|
|
phx
|
|
pha ;BlockSize (size still in Accumulator)
|
|
pea uFileBuff ;Owner
|
|
pea attrLocked ;Attributes
|
|
phx ;Location
|
|
phx
|
|
|
|
_NewHandle
|
|
plx ;output Handle
|
|
ply
|
|
bcs error
|
|
|
|
txa
|
|
jsr DeRef ;dereference Handle
|
|
sta |File_Buff ;save address in Globals
|
|
sty |File_Buff+2
|
|
sta FileBuff ;save address in Zero Page
|
|
sty FileBuff+2
|
|
;
|
|
; initialize File variables
|
|
;
|
|
stz |File_EOB ;File Buffer EOB
|
|
zero_marks
|
|
stz |File_Mark ;File Mark
|
|
stz |File_Mark+2
|
|
stz |Header_Mark ;Segment Header File Mark
|
|
stz |Header_Mark+2
|
|
stz |File_Pt ;File Buffer Pointer
|
|
;
|
|
; initialize Mark List
|
|
;
|
|
stz MarkList
|
|
stz MarkList+2
|
|
error
|
|
rts
|
|
|
|
EndP
|
|
|
|
TITLE ', FILES.a - Open_File'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Open File
|
|
*
|
|
* Inputs: Address of Pathname (TOS+11) - must be type 1 string
|
|
* Time/Date Stamp (TOS+3)
|
|
*
|
|
* Outputs: A - status code
|
|
* C - set if error
|
|
*
|
|
* Zero Page used: TempZero
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Open_File PROC
|
|
with DirectPage, Globals
|
|
|
|
Pathname equ 11
|
|
Date equ 3
|
|
;
|
|
; zero refnum in Open packet
|
|
;
|
|
stz |POpen.refNum
|
|
;
|
|
; check if Memory Load requested
|
|
;
|
|
lda Memory_Load
|
|
beq cont2
|
|
;
|
|
; yes, set File Buffer variables to contents of packet. In essence,
|
|
; the File in memory will act as the Loader's File Buffer
|
|
;
|
|
lda Pathname,s
|
|
sta TempZero
|
|
lda Pathname+2,s
|
|
sta TempZero+2
|
|
lda [TempZero]
|
|
sta |File_Buff
|
|
sta FileBuff
|
|
ldy #2
|
|
lda [TempZero],y
|
|
sta |File_Buff+2
|
|
sta FileBuff+2
|
|
ldy #4
|
|
lda [TempZero],y
|
|
sta |File_Buff_Size
|
|
sta |File_EOB
|
|
jsr zero_marks
|
|
jmp normal_exit
|
|
;
|
|
; see if file is already opened by getting its refnum from GS/OS
|
|
;
|
|
cont2 lda #2
|
|
sta |PGetRefNum.pCount ;parameter count
|
|
lda Pathname,s
|
|
sta |PGetRefNum.pathname ;pathname
|
|
lda Pathname+2,s
|
|
sta |PGetRefNum.pathname+2
|
|
jsl $E100A8
|
|
dc.w GetRefNum
|
|
dc.l PGetRefNum
|
|
bcs cont3
|
|
;
|
|
; file is already open, so put its refnum into the Open packet and skip open
|
|
;
|
|
lda |PGetRefNum.refNum
|
|
sta |POpen.refNum
|
|
jmp cont7
|
|
;
|
|
; setup Open packet
|
|
;
|
|
cont3 lda #10
|
|
sta |POpen.pCount ;parameter count
|
|
lda Pathname,s
|
|
sta |POpen.pathname ;pathname
|
|
lda Pathname+2,s
|
|
sta |POpen.pathname+2
|
|
lda #1
|
|
sta |POpen.requestAccess ;access code (read_only)
|
|
stz |POpen.resourceNumber ;resource number
|
|
;
|
|
; get system file level
|
|
;
|
|
lda #2
|
|
sta |PGetLevel.pCount ;parameter count
|
|
stz |PGetLevel.levelMode ;mode
|
|
jsl $E100A8
|
|
dc.w GetLevel
|
|
dc.l PGetLevel
|
|
;
|
|
; set system file level to $70
|
|
;
|
|
lda #2
|
|
sta |PSetLevel.pCount ;parameter count
|
|
lda #$70
|
|
sta |PSetLevel.level ;system file level
|
|
stz |PSetLevel.levelMode ;mode
|
|
jsl $E100A8
|
|
dc.w SetLevel
|
|
dc.l PSetLevel
|
|
;
|
|
; open file
|
|
;
|
|
jsl $E100A8
|
|
dc.w Open
|
|
dc.l POpen
|
|
php ;save status
|
|
pha
|
|
;
|
|
; restore system file level to its original value
|
|
;
|
|
lda |PGetLevel.level
|
|
sta |PSetLevel.level ;system file level
|
|
jsl $E100A8
|
|
dc.w SetLevel
|
|
dc.l PSetLevel
|
|
;
|
|
; check open status
|
|
;
|
|
pla
|
|
plp
|
|
bcs error
|
|
;
|
|
; check file type
|
|
;
|
|
lda |POpen.fileType ;get file_type
|
|
cmp #Load_File ;is it in range of Load File types?
|
|
bcc cont4
|
|
cmp #Last_Load_File+1
|
|
bcc cont5
|
|
cmp #CDev_File ;is it a CDev?
|
|
beq cont5 ;yes, we can load it.
|
|
;
|
|
; Not Load File error
|
|
;
|
|
cont4 lda #NotLoad
|
|
bra error
|
|
;
|
|
; compare input time/date stamp (if not zero) with file's
|
|
;
|
|
cont5 lda Date,s
|
|
beq cont7
|
|
cmp |POpen.modDateTime
|
|
bne cont6
|
|
lda Date+2,s
|
|
cmp |POpen.modDateTime+2
|
|
bne cont6
|
|
lda Date+4,s
|
|
cmp |POpen.modDateTime+4
|
|
bne cont6
|
|
lda Date+6,s
|
|
cmp |POpen.modDateTime+6
|
|
beq cont7
|
|
;
|
|
; time/date stamps do not compare - Bad Version error
|
|
;
|
|
cont6 lda #BadVers
|
|
error_skip
|
|
bra error
|
|
;
|
|
; move ref_num to other ProDOS packets
|
|
;
|
|
cont7 lda |POpen.refNum
|
|
sta |PRead.fileRefNum
|
|
sta |PGetMark.markRefNum
|
|
sta |PSetMark.markRefNum
|
|
|
|
jsl $E100A8 ;get the file's EOF
|
|
dc.w GET_EOF
|
|
dc.l PGetMark ;borrow this parameter block
|
|
|
|
lda PGetMark.position ;is there anything in the file?
|
|
ora PGetMark.position+2
|
|
beq cont4 ;no, can't be a load file
|
|
|
|
jsr Setup_Buf_Ptrs
|
|
bcs error
|
|
|
|
normal_exit
|
|
lda #0 ;set status to OK
|
|
error Stack_Cleanup 12 ;remove input parameters
|
|
rts ;return
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Close_File'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Close File
|
|
*
|
|
* Inputs: none
|
|
*
|
|
* Outputs: A - status code
|
|
* C - set if error
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
* If Keep_Open is true, the file is not really closed
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Close_File PROC
|
|
with DirectPage, Globals
|
|
|
|
;
|
|
; if Memory_Load is set, only dispose of the buffers
|
|
;
|
|
lda Memory_Load
|
|
bne cont1
|
|
;
|
|
; if RefNum is zero, don't issue close
|
|
;
|
|
lda |POpen.refNum
|
|
beq cont1
|
|
;
|
|
; if Keep_Open is true, don't issue close
|
|
;
|
|
lda Keep_Open
|
|
bne cont1
|
|
;
|
|
; close file
|
|
;
|
|
lda POpen.refNum ;do we have a valid refnum?
|
|
beq cont1 ;no, so don't do a global close!
|
|
|
|
jsl $E100A8
|
|
dc.w PD_CLOSE
|
|
dc.l POpen.refNum
|
|
bcs error
|
|
;
|
|
; dispose of File Buffers
|
|
;
|
|
cont1 pea uFileBuff ;Owner
|
|
|
|
_DisposeAll
|
|
|
|
error stz |POpen.refNum ;zero refnum
|
|
stz file_open ;zero flag
|
|
rts ;return
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Fill_File_Buff'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Refill File Buffer
|
|
*
|
|
* Inputs: none
|
|
*
|
|
* Outputs: A - status
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Fill_File_Buff PROC
|
|
with DirectPage, Globals
|
|
;
|
|
; set File_Mark to current File Mark
|
|
;
|
|
jsl $E100A8
|
|
dc.w GET_MARK
|
|
dc.l PGetMark
|
|
bcs error
|
|
|
|
lda |PGetMark.position
|
|
sta |File_Mark
|
|
lda |PGetMark.position+2
|
|
sta |File_Mark+2
|
|
;
|
|
; fill buffer by reading file
|
|
;
|
|
lda |File_Buff
|
|
sta |PRead.dataBuffer ;buffer address
|
|
lda |File_Buff+2
|
|
sta |PRead.dataBuffer+2
|
|
lda |File_Buff_Size
|
|
sta |PRead.requestCount ;# of bytes to read
|
|
stz |PRead.requestCount+2
|
|
|
|
jsl $E100A8
|
|
dc.w PD_READ
|
|
dc.l PRead
|
|
bcs error
|
|
;
|
|
; set File_Pt and File_EOB
|
|
;
|
|
lda |PRead.transferCount
|
|
sta |File_EOB ;# of bytes actually read
|
|
stz |File_Pt ;zero File Pointer
|
|
lda #0 ;carry already clear
|
|
error rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Save_Mark'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Save OP Mark in Mark List
|
|
*
|
|
* Inputs: OP_Mark - File Mark of current OP code
|
|
* CSegNum - current Segment Number
|
|
*
|
|
* Outputs: Mark List updated
|
|
* A - status
|
|
* C - set if error occurred
|
|
*
|
|
* Zero Page used: TempZero, Handle
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Save_Mark PROC
|
|
with DirectPage
|
|
|
|
Size_Header equ ML_FirstEntry ;# of bytes in List header
|
|
Size_Incr equ 100 ;# of entries in each expansion
|
|
;
|
|
; if the address of the Mark List=0, create a new one
|
|
;
|
|
lda MarkList
|
|
ora MarkList+2
|
|
bne cont1
|
|
|
|
ldx #0 ;output Handle
|
|
phx
|
|
phx
|
|
pea ML_SizeEntry*Size_Incr+Size_Header>>16 ;BlockSize
|
|
pea |ML_SizeEntry*Size_Incr+Size_Header
|
|
pea uMarkList ;Owner
|
|
pea attrLocked+attrNoSpec ;Attributes
|
|
phx ;Location
|
|
phx
|
|
|
|
_NewHandle
|
|
plx ;output Handle
|
|
ply
|
|
bcc @1
|
|
jmp error
|
|
@1
|
|
txa
|
|
jsr DeRef ;dereference Handle
|
|
sta MarkList ;save address in Zero Page
|
|
sty MarkList+2
|
|
;
|
|
; set Next Available Slot to Size_Header and set End of List to
|
|
; ML_SizeEntry*Size_Incr+Size_Header
|
|
;
|
|
lda #Size_Header
|
|
sta [MarkList]
|
|
lda #ML_SizeEntry*Size_Incr+Size_Header
|
|
ldy #4
|
|
sta [MarkList],y
|
|
lda #0
|
|
ldy #2
|
|
sta [MarkList],y
|
|
ldy #6
|
|
sta [MarkList],y
|
|
;
|
|
; is there any more room in Mark List ?
|
|
; (if Next Available Slot = End of List then List is full)
|
|
;
|
|
cont1 lda [MarkList] ;Next Available Slot
|
|
ldy #4
|
|
cmp [MarkList],y ;End of List
|
|
bne cont3
|
|
ldy #2
|
|
lda [MarkList],y
|
|
ldy #6
|
|
cmp [MarkList],y
|
|
bne cont3
|
|
;
|
|
; no more room, get handle to Mark List
|
|
;
|
|
cont2 pei MarkList+2 ;address of Mark List
|
|
pei MarkList
|
|
_FindHandle
|
|
lda 1,s
|
|
sta Handle ;retrieve handle
|
|
lda 3,s ;but leave on stack for HUnlock call
|
|
sta Handle+2
|
|
;
|
|
; unlock Mark List
|
|
;
|
|
_HUnlock
|
|
;
|
|
; expand Mark List by another ML_SizeEntry*Size_Incr
|
|
;
|
|
ldy #4
|
|
lda [MarkList],y
|
|
clc
|
|
adc #ML_SizeEntry*Size_Incr
|
|
sta TempZero
|
|
tax
|
|
ldy #6
|
|
lda [MarkList],y
|
|
adc #0
|
|
sta TempZero+2
|
|
|
|
pha
|
|
phx ;Size
|
|
pei Handle+2 ;Handle
|
|
pei Handle
|
|
_SetHandleSize
|
|
bcs error
|
|
;
|
|
; lock Mark List
|
|
;
|
|
pei Handle+2 ;Handle
|
|
pei Handle
|
|
_HLock
|
|
;
|
|
; get new address of Mark List
|
|
;
|
|
lda Handle
|
|
ldy Handle+2
|
|
jsr DeRef ;dereference Handle
|
|
sta MarkList
|
|
sty MarkList+2
|
|
;
|
|
; set End of List to new value
|
|
;
|
|
lda TempZero
|
|
ldy #4
|
|
sta [MarkList],y
|
|
lda TempZero+2
|
|
ldy #6
|
|
sta [MarkList],y
|
|
;
|
|
; calculate address of Next Available Slot
|
|
;
|
|
cont3 lda MarkList
|
|
clc
|
|
adc [MarkList]
|
|
sta TempZero
|
|
lda MarkList+2
|
|
ldy #2
|
|
adc [MarkList],y
|
|
sta TempZero+2
|
|
;
|
|
; store Segment Number and Op_Mark in Next Available Slot
|
|
;
|
|
lda CSegNum
|
|
sta [TempZero]
|
|
lda Op_Mark
|
|
ldy #2
|
|
sta [TempZero],y
|
|
lda Op_Mark+2
|
|
ldy #4
|
|
sta [TempZero],y
|
|
;
|
|
; increment Next Available Slot by ML_SizeEntry
|
|
;
|
|
lda [MarkList]
|
|
clc
|
|
adc #ML_SizeEntry
|
|
sta [MarkList]
|
|
bcc return
|
|
ldy #2
|
|
lda [MarkList],y
|
|
inc a
|
|
sta [MarkList],y
|
|
|
|
return lda #0
|
|
clc
|
|
error rts
|
|
|
|
ENDP
|
|
|
|
TITLE ', FILES.a - Bump_Mark'
|
|
*
|
|
****************************************************************
|
|
*
|
|
* Bump Header_Mark to next Header
|
|
*
|
|
* Inputs: Header - current Segment Header
|
|
* Header_Mark - File Mark of Segment Header
|
|
*
|
|
* Outputs: Header_Mark - File Mark of next Segment Header
|
|
*
|
|
* Zero Page used: none
|
|
*
|
|
****************************************************************
|
|
*
|
|
|
|
Bump_Mark PROC
|
|
with DirectPage, Globals
|
|
;
|
|
; if Version<2, convert BYTECNT to bytes (*512)
|
|
;
|
|
lda Header.Version
|
|
cmp #2
|
|
bcs cont
|
|
|
|
ldx #9
|
|
lda Header.ByteCnt
|
|
@loop
|
|
asl a
|
|
rol Header.ByteCnt+2
|
|
dex
|
|
bne @loop
|
|
sta Header.ByteCnt
|
|
;
|
|
; increment input Mark by BYTECNT to get output mark
|
|
;
|
|
cont lda |Header_Mark
|
|
clc
|
|
adc Header.ByteCnt
|
|
sta |Header_Mark
|
|
lda |Header_Mark+2
|
|
adc Header.ByteCnt+2
|
|
sta |Header_Mark+2
|
|
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|