Files
Shawn Quick dfcaae62dd Add qlink, the disk tools, and a bootable ProDOS 8 image.
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.
2026-10-16 14:41:55 -07:00

1 line
27 KiB
Plaintext

eject
;====================================================================================================
;get_seg_base: Given a segment number this routine will setup segment_base
;
;Input: A = segment_number
; X = undefined
; Y = undefined
; P = nvmxdizc
; ..000...
; b = k
;
; HET_ptr ;must be setup!
;
;Output: A = undefined
; X = undefined
; Y = undefined
; P = nvmxdizc
; ..000...
; b = k
;
;
;====================================================================================================
longa on
longi on
get_seg_base proc
with data
dec a ;HET table numbers are 0 thru (-n- minus 1)
sec
sbc >data.ExpressSeg_pos
asl a
asl a
asl a ;times 8 for HET entry size
inc a ;add two to pass the segment count field
inc a
clc
adc HET_ptr ;make a pointer to the Entry
sta HET_Entry_ptr ;pointer to the entry itself
lda #$0000
adc HET_ptr+2
sta HET_Entry_ptr+2
;
;Now we need to setup our Base address for this segment
;
ldy #$0004 ;index to the handle
lda [HET_entry_ptr],y
sta Temp_Handle
iny
iny
lda [HET_Entry_ptr],y
sta temp_handle+2
;
;Deref the handle to find out the base address
;
ldy #$0002
lda [temp_handle]
sta segment_base ;starting address of the segment
lda [temp_handle],y
sta segment_base+2
ora segment_base ;see if the segment has been purged!
bne @segment_alive ;great.
lda #seg_not_found
sec
rts
@segment_alive
clc
rts
eject
;====================================================================================================
;Process_Reloc: This routine is called to process the relocation dictionary of a segment
; ** NOTE ** This code changes the data bank register to the bank that
; contains the Relocation Dictionary. This means all data access to data in
; our bank must use long addressing.
;
;Input: A = segment number to relocate
; X = undefined
; Y = undefined
; P = nvmxdizc
; ..000...
; b = k
;
; HET_ptr ;pointer to HET (Header Entry Table) must be setup!
;
;Output: A = undefined
; X = undefined
; Y = undefined
; P = nvmxdizc
; ..000...
; b = k
;
;
;
;-Note-
; All Segments that this segment links to must be loaded into memory
;
;HET Entry definition:
;
; -------------------
; Number of segments (word)
; -------------------
; ¥
; ¥
; ¥
; ------------------- [This is one Header Entry, it is repeated -n- times]
; Relative offset to
; segment header (word)
; -------------------
; Flags (word) Bit 15 = loaded
; -------------------
; Handle to segment (Long) Points to the segment in memory
; -------------------
; ¥
; ¥
; ¥
;
;====================================================================================================
longa on
longi on
Process_Reloc proc
with data
sta reloc_seg ;segment numbers are 1 thru -n-
jsr setup_seg_ptrs ;build pointers to the segment entries
IF debug_on=0 GOTO .nobug
lda #$EEEE
sta >Rom_debug+4
.nobug
;
;Now we need to setup our Base address for this segment
;
ldy #$0004 ;index to the handle
lda [HET_entry_ptr],y
sta Temp_Handle
iny
iny
lda [HET_Entry_ptr],y
sta temp_handle+2
;
;Deref the handle to find out the base address
;
ldy #$0002
lda [temp_handle]
sta base_ptr ;starting address of the segment
lda [temp_handle],y
sta base_ptr+2
ora base_ptr ;see if the segment has been purged!
bne @segment_alive ;great.
@no_seg
sec
lda #seg_not_found ;sorry we cannot process the segment
rts
;
;Now we need to deref the handle to the relocation dictionary
;The handle for the relocation dictionary is located in the segment header
;
@segment_alive
ldy #reloc_size_offset ;now lets get the size of the segment
lda [seg_header_ptr],y
bne @its_there
iny
iny
lda [seg_header_ptr],y
bne @its_there
clc
rts ;easy case
@its_there
ldy #Reloc_dict_offset ;offset to the relocation dictionary handle
lda [seg_header_ptr],y ;get the handle
sta temp_handle
iny
iny
lda [seg_header_ptr],y
sta temp_handle+2
;
;now lets deref the handle and build a pointer to the relocation dictionary
;
ldy #$0002
lda [temp_handle]
sta reloc_dict_ptr ;points the relocation dictionary in memory
lda [temp_handle],y
sta reloc_dict_ptr+2
ora reloc_dict_ptr ;is the dictionary available
beq @no_seg
stz end_found ;indicate there are records to process
stz patch_cnt
stz shift_cnt
lda reloc_dict_ptr+1 ;set the data bank register to relocation dictionary
pha
plb ;get the Bank Address of Relocation Dictionary
plb
opcode_loop
lda (reloc_dict_ptr) ;get the current opcode
and #$00FF ;clear any garbage
beq do_end_handler ;this is the end handler
asl a ;times two for word table
tax
jsr (opcode_handlers-$1C4,x) ;Subtract of base of opcodes ($1C4 = $E2*2)
bcc opcode_loop ;do the next opcode please
phk
plb ;restore our bank
rts ;return the error code
;
;This routine dispatches to the correct opcode handler
;
do_end_handler
pea we_are_done-1 ;this is the last one!
pea end_handler-1
rts
we_are_done
phk
plb ;restore our bank please
IF debug_on=0 GOTO .nobug
lda #$BBBB
sta >Rom_debug+6
.nobug
ldy #Reloc_dict_offset+2 ;offset to the relocation dictionary handle
lda [seg_header_ptr],y ;get the handle
pha
lda #$0000
sta [seg_header_ptr],y
dey
dey
lda [seg_header_ptr],y
pha
lda #$0000
sta [seg_header_ptr],y
ldx #$1002 ;dispose handle
jsl $e10000
stz temp_handle ;make sure we note that the handle is invalid
stz temp_handle+2
clc
rts ;we did it!!!!
bad_opcode
sec
lda #illegal_record
rts ;exit with error
opcode_handlers
dc.w Reloc_handler ;$E2
dc.w Interseg_handler ;$E3
dc.w bad_opcode ;$E4
dc.w bad_opcode ;$E5
dc.w bad_opcode ;$E6
dc.w bad_opcode ;$E7
dc.w bad_opcode ;$E8
dc.w bad_opcode ;$E9
dc.w bad_opcode ;$EA
dc.w bad_opcode ;$EB
dc.w bad_opcode ;$EC
dc.w bad_opcode ;$ED
dc.w bad_opcode ;$EE
dc.w bad_opcode ;$EF
dc.w bad_opcode ;$F0
dc.w bad_opcode ;$F1
dc.w bad_opcode ;$F2
dc.w bad_opcode ;$F3
dc.w bad_opcode ;$F4
dc.w cReloc_handler ;$F5
dc.w cInterseg_handler ;$F6
dc.w Super_handler ;$F7
eject
;====================================================================================================
;
;This routine will process a standard relocation entry
;
;Structure pointed to by Reloc_dict_ptr
;
; opcode $E2 (1 Byte)
; patch_cnt (1 byte: number of bytes to patch)
; bit_shift (1 byte: (+) = ASL (-) = LSR
; patch_offset (4 bytes: offset from the start of the segment)
; patch_value (4 bytes: offset from the start of the segment)
;
;====================================================================================================
Reloc_handler
ldy #$0001
lda (reloc_dict_ptr),y ;get the patch cnt and bit shift
sep #$20
sta patch_cnt ;the number of bytes to patch 1,2 or 3
xba
sta shift_cnt
rep #$20 ;back to 16 bit mode
ldy #$0003 ;point to the patch offset
clc
lda (reloc_dict_ptr),y
adc base_ptr ;base address
sta patch_ptr ;address to patch
ldy #$0005
lda (reloc_dict_ptr),y
adc base_ptr+2
sta patch_ptr+2 ;high word of patch address
ldy #$0007 ;point to the patch value field
clc
lda (reloc_dict_ptr),y
adc base_ptr
sta patch_value
ldy #$0009
lda (reloc_dict_ptr),y
adc base_ptr+2
sta patch_value+2 ;what we will patch with
clc
lda reloc_dict_ptr ;bump the relocation dictionary pointer please
adc #$000b
sta reloc_dict_ptr
bcc @low_only
inc reloc_dict_ptr+2 ;don't forget the high byte please
lda reloc_dict_ptr+1
pha
plb
plb ;setup for the new bank please
@low_only
jmp shift_patch ;the the patch please
eject
;====================================================================================================
;
;This routine will process a compressed relocation entry
;
;Structure pointed to by Reloc_dict_ptr
;
; opcode $F5 (1 Byte)
; patch_cnt (1 byte: number of bytes to patch)
; bit_shift (1 byte: (+) = ASL (-) = LSR
; patch_offset (2 bytes: offset from the start of the segment)
; patch_value (2 bytes: offset from the start of the segment)
;
;====================================================================================================
cReloc_handler
ldy #$0001
lda (reloc_dict_ptr),y ;get the patch cnt and bit shift
sep #$20
sta patch_cnt ;the number of bytes to patch 1,2 or 3
xba
sta shift_cnt
rep #$20 ;back to 16 bit mode
ldy #$0003 ;point the patch offset
clc
lda (reloc_dict_ptr),y
adc base_ptr ;base address
sta patch_ptr ;address to patch
lda #$0000
adc base_ptr+2
sta patch_ptr+2 ;high word of patch address
ldy #$0005 ;point to the patch value field
clc
lda (reloc_dict_ptr),y
adc base_ptr
sta patch_value
lda #$0000
adc base_ptr+2
sta patch_value+2 ;what we will patch with
clc
lda reloc_dict_ptr ;bump the relocation dictionary pointer please
adc #$0007
sta reloc_dict_ptr
bcc @low_only
inc reloc_dict_ptr+2 ;don't forget the high byte please
pei reloc_dict_ptr+1
plb
plb ;setup for the new bank please
@low_only
jmp shift_patch ;the the patch please
eject
;====================================================================================================
;
;This routine will process a Interseg relocation entry
;
;Structure pointed to by Reloc_dict_ptr
;
; opcode $E3 (1 Byte)
; patch_cnt (1 byte: number of bytes to patch)
; bit_shift (1 byte: (+) = ASL (-) = LSR
; patch_offset (4 bytes: offset from the start of the segment)
; file number (2 bytes: file number of load file: not supported yet)
; segment number (2 bytes: segment that we are linking to)
; patch_value (4 bytes: offset from the start of the destination segment)
;
;====================================================================================================
Interseg_handler
ldy #$0001
lda (reloc_dict_ptr),y ;get the patch cnt and bit shift
sep #$20
sta patch_cnt ;the number of bytes to patch 1,2 or 3
xba
sta shift_cnt
rep #$20 ;back to 16 bit mode
ldy #$0003 ;point the patch offset
clc
lda (reloc_dict_ptr),y
adc base_ptr ;base address
sta patch_ptr ;address to patch
ldy #$0005
lda (reloc_dict_ptr),y
adc base_ptr+2
sta patch_ptr+2 ;high word of patch address
ldy #$0007 ;now lets point to the file number
lda (reloc_dict_ptr),y
dec a ;better be one
beq @great
sec
lda #illegal_record
rts ;return the error
@great
ldy #$0009 ;get the segment number
lda (reloc_dict_ptr),y
and #$00FF
jsr get_seg_base
bcc @got_it
rts
@got_it
ldy #$000B ;offset to relative address in destination seg
clc
lda (reloc_dict_ptr),y
adc segment_base
sta patch_value
ldy #$000D
lda (reloc_dict_ptr),y
adc segment_base+2
sta patch_value+2
clc
lda reloc_dict_ptr ;bump the relocation dictionary pointer please
adc #$000F
sta reloc_dict_ptr
bcc @low_only
inc reloc_dict_ptr+2 ;don't forget the high byte please
lda reloc_dict_ptr+1
pha
plb
plb ;setup for the new bank please
@low_only
jmp shift_patch ;patch the segment please
eject
;====================================================================================================
;
;This routine will process a compressed Interseg relocation entry
;
;Structure pointed to by Reloc_dict_ptr
;
; opcode $F6 (1 Byte)
; patch_cnt (1 byte: number of bytes to patch)
; bit_shift (1 byte: (+) = ASL (-) = LSR
; patch_offset (2 bytes: offset from the start of the segment)
; segment number (1 bytes: segment that we are linking to)
; patch_value (2 bytes: offset from the start of the destination segment)
;
;====================================================================================================
cInterseg_handler
ldy #$0001
lda (reloc_dict_ptr),y ;get the patch cnt and bit shift
sep #$20
sta patch_cnt ;the number of bytes to patch 1,2 or 3
xba
sta shift_cnt
rep #$20 ;back to 16 bit mode
ldy #$0003 ;point the patch offset
clc
lda (reloc_dict_ptr),y
adc base_ptr ;base address
sta patch_ptr ;address to patch
lda #$0000
adc base_ptr+2
sta patch_ptr+2 ;high word of patch address
ldy #$0005 ;get the segment number
lda (reloc_dict_ptr),y
and #$00FF ;one byte segment number
jsr get_seg_base
bcc @got_it
rts
@got_it
ldy #$0006 ;offset to relative address in destination seg
clc
lda (reloc_dict_ptr),y
adc segment_base
sta patch_value
lda #$0000
adc segment_base+2
sta patch_value+2
clc
lda reloc_dict_ptr ;bump the relocation dictionary pointer please
adc #$0008
sta reloc_dict_ptr
bcc @low_only
inc reloc_dict_ptr+2 ;don't forget the high byte please
lda reloc_dict_ptr+1
pha
plb
plb ;setup for the new bank please
@low_only
jmp shift_patch ;patch the segment please
eject
;====================================================================================================
;Super_Handler This one is a bitch.
;
;There are several types of super records. Below is the list that I support.
;
; 1) Reloc2
; 2) Reloc3
; 3) Interseg1-Interseg36
;
;
;Super record structure:
;
; opcode $F7 ;byte
; ------------------------
; size of record ;long
; ------------------------
; record type ;byte
; ------------------------
; patch info: example
;
; $01 ;patch two bytes in page one of load segment
; $34 ;offset to 1st byte in page one of load segment
; $7A ;offset to 2nd byte in page one of load segment
; $81 ;skip 1 page. (High bit means lower 7 bits contain skip cnt)
; $00 ;patch one byte in page three of load segment
; $82 ;offset in page three to patch
;
;====================================================================================================
super_handler
lda base_ptr ;address of the segment
sta temp_ptr
lda base_ptr+2
sta temp_ptr+2
clc
lda reloc_dict_ptr
adc #$0006 ;pass the record type
sta super_ptr
lda reloc_dict_ptr+2
adc #$0000
sta super_ptr+2
ldy #$0001 ;get the total count of entries please
lda (reloc_dict_ptr),y ;get the size of the Super Record
sta super_size
dec a ;remove one for the opcode byte
sta cnt_word
ldy #$0003
lda (reloc_dict_ptr),y ;fail if non-zero
beq @size_ok
sec
lda #illegal_record
rts ;return the error
@size_ok
ldy #$0005 ;pass the size field
lda (reloc_dict_ptr),y
and #$00FF ;clear the garbage
tax
beq @reloc2_type ;do a reloc 2 type
dec a
beq @reloc3_type
;
;If we get here we know that this is an Interseg Record of some kind
;
txa ;get back the kind again
cmp #26
bcc @chk_14
jsr Interseg_26
bra @end_super ;we are done
@chk_14
cmp #14
bcc @one_thru_12
jsr Interseg_14 ;do the conversion
bra @end_super
@one_thru_12
jsr Interseg_1
bra @end_super
@reloc2_type
jsr reloc2
bra @end_super
@reloc3_type
jsr reloc3
@end_super
bcs @abort
lda super_size ;size of the data area
adc #$0005 ;overhead in record
clc
adc reloc_dict_ptr ;bump the relocation dictionary pointer please
sta reloc_dict_ptr
bcc @low_only
inc reloc_dict_ptr+2 ;don't forget the high byte please
lda reloc_dict_ptr+1
pha
plb
plb ;setup for the new bank please
@low_only
clc
@abort
rts
eject
;====================================================================================================
;Interseg1 This routine is used to patch Super interseg records 1 thru 12:
;
;structure:
;
; If the opcode field is 3 thru 13 then this value indicates
; the file number (plus 1) to load from. I do not support this.
;
; relocation information is in the operand field of load segment.
; Format:
; Offset ;word
; segment number ;byte number of segment to link to.
;
;
;====================================================================================================
Interseg_1
ldy #$0005 ;lets get the segment number
lda (reloc_dict_ptr),y
and #$00FF ;get the record type
cmp #$0003 ;is the number 2 thru 12?
bcc @good_seg
lda #illegal_record ;sorry illegal record type
@good_seg
ldy #$0000
lda cnt_word ;see if we are done yet
beq @done
@outter_loop
lda [super_ptr],y ;get the command (8 Bits)
bit #$0080 ;clear all but the pages bit
beq @do_inner_loop ;process the relocation info
and #$007F ;get the number of pages to skip
xba ;multiply the number times 256
clc
adc temp_ptr
sta temp_ptr
bcc @low_only
inc temp_ptr+2
@low_only
iny ;bump index to the next byte
dec cnt_word ;reduce the count by one
bne @outter_loop
@done
clc
rts ;we are done
@do_inner_loop
and #$007F ;number of entries we have to patch
tax
@inner_loop
dec cnt_word ;reduce the count by one
iny ;bump index to the next byte
lda [super_ptr],y ;A = offset
and #$00FF ;clear garbage
phy ;save the index please
tay
phy ;index to patch area
lda [temp_ptr],y ;get the relative offset in other segment
sta patch_value
iny
iny
lda [temp_ptr],y ;get the segment number to patch to
and #$00FF
jsr get_seg_base ;go and get the segment base address
ply ;get our index back please
bcc @have_segment
ply ;remove super index please
rts ;return the error
@have_segment
clc
lda segment_base
adc patch_value
sta [temp_ptr],y
iny
iny
lda segment_base+2
adc #$0000
sep #$20 ;8 bit store only
sta [temp_ptr],y ;save the new address please
rep #$20 ;16 bit mode
ply ;restore super index
dex
bpl @inner_loop ;process this page
iny ;bump to next byte
inc temp_ptr+1 ;add 256 to the page pointer
dec cnt_word ;reduce the count by one
bne @outter_loop
clc
rts
eject
;====================================================================================================
;Interseg_14 This routine processes interseg 14 thru interseg 24 types.
; This type allows a 16 bit patch with no shifting.
;
;Structure:
;
; The segment number to process is in the opcode byte. To determine
; the real segment number just subtract 13 from the stored value.
;
;====================================================================================================
Interseg_14
ldy #$0005 ;lets get the segment number
sec
lda (reloc_dict_ptr),y
and #$00FF ;get the record type
sbc #13
jsr get_seg_base ;setup the base address for this segment
ldy #$0000 ;init super index
bcc @continue
rts ;return the error
@continue
lda cnt_word ;see if we are done yet
beq @done
@outter_loop
lda [super_ptr],y ;get the command (8 Bits)
bit #$0080 ;clear all but the pages bit
beq @do_inner_loop ;process the relocation info
and #$007F ;get the number of pages to skip
xba ;multiply the number times 256
clc
adc temp_ptr
sta temp_ptr
bcc @low_only
inc temp_ptr+2
@low_only
iny ;bump index to the next byte
dec cnt_word ;reduce the count by one
bne @outter_loop
@done
clc
rts
@do_inner_loop
and #$007F ;number of entries we have to patch
tax
@inner_loop
dec cnt_word ;reduce the count by one
iny ;point to the next byte
lda [super_ptr],y ;A = offset
and #$00FF ;clear garbage
phy ;save super index
tay ;build patch record index
clc ;do the 16 bit patch
lda [temp_ptr],y ;get the relative offset in other segment
adc segment_base
sta [temp_ptr],y
ply ;get back super index
dex
bpl @inner_loop ;process this page
iny ;point to the next byte
inc temp_ptr+1 ;point to the next page please
dec cnt_word ;reduce the count by one
bne @outter_loop
clc
rts
eject
;====================================================================================================
;Interseg_26 This routine processes interseg 25 thru interseg 36 types.
; This type allows a 16 bit patch with 16 bit shifting.
;
;Structure:
;
; The segment number to process is in the opcode byte. To determine
; the real segment number just subtract 25 from the stored value.
;====================================================================================================
Interseg_26
ldy #$0005 ;lets get the segment number
sec
lda (reloc_dict_ptr),y
and #$00FF ;get the record type
sbc #25
jsr get_seg_base ;setup the base address for this segment
ldy #$0000 ;init the super index pointer
bcc @continue
rts ;return the error
@continue
lda cnt_word ;see if we are done yet
beq @done
@outter_loop
lda [super_ptr],y ;get the command (8 Bits)
bit #$0080 ;clear all but the pages bit
beq @do_inner_loop ;process the relocation info
and #$007F ;get the number of pages to skip
xba ;multiply the number times 256
clc
adc temp_ptr
sta temp_ptr
bcc @low_only
inc temp_ptr+2
@low_only
iny ;bump index to point to the next byte
dec cnt_word ;reduce the count by one
bne @outter_loop
@done
clc
rts
@do_inner_loop
and #$007F ;number of entries we have to patch
tax
@inner_loop
dec cnt_word ;reduce the count by one
iny ;point to the next byte
lda [super_ptr],y ;A = offset
and #$00FF ;clear garbage
phy ;save super index
tay ;build index to patch address
lda [temp_ptr],y ;get the relative offset in other segment
sta patch_value
clc ;do the 16 bit patch
lda segment_base
adc patch_value
lda segment_base+2 ;store the upper 16 bits only
adc #$0000
sta [temp_ptr],y
ply ;restore super index
dex
bpl @inner_loop ;process this page
iny ;point to the next byte
inc temp_ptr+1 ;bump to the next page
dec cnt_word ;reduce the count by one
bne @outter_loop
clc
rts
eject
;====================================================================================================
Reloc2
ldy #$0000 ;init the index
@outter_loop
lda cnt_word ;see if we are done yet
bne @not_yet
clc
rts ;we are done
@not_yet
lda [super_ptr],y ;get the command (8 Bits)
bit #$0080 ;clear all but the pages bit
beq @do_inner_loop ;process the relocation info
and #$007F ;get the number of pages to skip
xba ;multiply the number times 256
clc
adc temp_ptr
sta temp_ptr
bcc @low_only
inc temp_ptr+2
@low_only
dec cnt_word ;reduce the count by one
iny ;bump index to the next byte
bra @outter_loop
@do_inner_loop
and #$007F ;number of entries we have to patch
tax
@inner_loop
dec cnt_word ;reduce the count by one
iny ;point to the next index please
lda [super_ptr],y ;A = offset
and #$00FF ;clear garbage
phy ;save super index
tay ;build index to the patch area
clc
lda [temp_ptr],y ;get the relative offset to patch with
adc base_ptr ;base address of segment
sta [temp_ptr],y
ply ;restore super index
dex
bpl @inner_loop ;process this page
dec cnt_word ;reduce the count by one
iny ;point to the next byte
inc temp_ptr+1 ;point to the next page please
bra @outter_loop
eject
;====================================================================================================
Reloc3
ldy #$0000 ;init super index to zero
@outter_loop
lda cnt_word ;see if we are done yet
bne @not_yet
clc
rts ;we are done
@not_yet
lda [super_ptr],y ;get the command (8 Bits)
bit #$0080 ;clear all but the pages bit
beq @do_inner_loop ;process the relocation info
and #$007F ;get the number of pages to skip
xba ;multiply the number times 256
clc
adc temp_ptr
sta temp_ptr
bcc @low_only
inc temp_ptr+2
@low_only
dec cnt_word ;reduce the count by one
iny ;point to next byte
bra @outter_loop
@do_inner_loop
and #$007F ;number of entries we have to patch
tax
@inner_loop
dec cnt_word ;reduce the count by one
iny ;point to next byte in super record
lda [super_ptr],y ;A = offset
and #$00FF ;clear garbage
phy ;save the super index please
tay
clc
lda [temp_ptr],y ;get the relative offset to patch with
adc base_ptr ;base address of segment
sta [temp_ptr],y
iny
iny
sep #$20 ;8 bit accumulator
lda [temp_ptr],y
adc base_ptr+2
sta [temp_ptr],y ;save the third byte please
rep #$20 ;16 bit accumulator
ply ;restore super index
dex
bpl @inner_loop ;process this page
dec cnt_word ;reduce the count by one
iny ;bump super record index
inc temp_ptr+1 ;bump to the next page please
bra @outter_loop
;====================================================================================================
;End_handler: Just sets the flag indicating that we are done.
;====================================================================================================
end_handler
lda #$FFFF
sta >end_found ;indicate that we are done!!!
rts
eject
;====================================================================================================
;
;Below is the common patch code. This code will do the relocation of the operand field
;
;====================================================================================================
shift_patch
longa off
sep #$20
lda shift_cnt ;number of times to shift
beq @no_shift ;very common case
cmp #$F0 ;load the 3rd byte of address
beq @skip_16_bits
cmp #$F8 ;load the 2nd byte of address
beq @skip_8_bits
;
;we have now handled the common cases. So lets do the odd cases now
;
lda shift_cnt
bpl @shift_left ;not a commom case
sec
lda #$00
sbc shift_cnt ;convert twos compliment please
;
;do the slow shift right
;
longa on
rep #$20 ;back to 16 bit mode
and #$00FF ;clear garbage
tax ;count
@right_loop
lsr patch_value+2
ror patch_value ;shift by amount in x
dex
bne @right_loop
bra patch_it ;continue the patch
@shift_left
longa on
rep #$20
and #$00FF
tax
@left_loop
asl patch_value
rol patch_value+2
dex
bne @left_loop ;shift the correct amount
bra patch_it ;continue the patch
@skip_16_bits ;equals a shift 16
longa on
rep #$20
lda patch_value+2 ;get the high word please
sta patch_value
bra patch_it
@skip_8_bits ;equals a shift 8
longa on
rep #$20
lda patch_value+1
sta patch_value
bra patch_it
@no_shift ;equals no shift
longa on
rep #$20
patch_it
ldy #$0000
lda patch_cnt ;number of bytes to patch
asl a
tax
lda >quick_jump-2,x
pha
rts
quick_jump
dc.w one_byte-1
dc.w two_byte-1
dc.w three_byte-1
dc.w four_byte-1
one_byte
sep #$20
lda patch_value
sta [patch_ptr] ;store the value
rep #$20
clc
rts
two_byte
lda patch_value
sta [patch_ptr]
clc
rts
three_byte
lda patch_value
sta [patch_ptr]
ldy #$0001
lda patch_value+1
sta [patch_ptr],y
clc
rts
four_byte
ldy #$0002
lda patch_value
sta [patch_ptr]
lda patch_value+2
sta [patch_ptr],y
clc
rts
endp