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
7.9 KiB
Plaintext

TITLE ', JUMP.a - JumpLoad'
*
****************************************************************
*
* Jump Table Load ($15)
*
* Inputs: UserID (2 bytes)
* Load File Number (2 bytes)
* Load Segment Number (2 bytes)
* Load Segment Offset (4 bytes)
*
* inputs are 'not' on stack but can found by tracing
* the return address back to the calling location. They
* are in locations before the JSL.
*
* Outputs: none
* Errors: $0000 - Operation successful
* $1101 - Segment not found
* $1102 - Segment not dynamic
* $1104 - File not Load File
* $00xx - ProDOS I/O error
* $02xx - Memory Manager error
*
****************************************************************
*
JumpLoad PROC
LoadSegCheck
with DirectPage, Globals
Import reset_local_mark,find_user_id,merge_path_2, \
lock_segment,open_load_file,error_routine, \
lock_handles,unlock_handles,load_segment, \
Process_Reloc,close_load_file
;
; the stack looks like this at entry:
;
; (previous contents)
; return to Jump Table entry (3 bytes)
; top of stack
;
php ;save user's P-register
phb ;save user's DBR
phk ;set to our bank
plb
;
; Now, the stack looks like this:
;
; (previous contents)
; return to Jump Table entry (3 bytes)
; user's processor status (1 byte)
; user's Data Bank Register (1 byte)
; top of stack
;
rep #$30 ;ensure 16-bit mode
sta save_a
stx save_x
sty save_y ;save app's registers
plx ;get the processor status + Bank register
pla ;get the low word of the return address
sta starting_addr
sep #$20 ;8 bit mode
pla
sta starting_addr+2 ;store the bank byte of the return address
stz starting_addr+3
rep #$20 ;16 bit
phx ;put status and DBR back on stack
phd ;save user's direct page
lda my_dir_page ;set to my direct page
tcd
;
; Now, the stack looks like this:
;
; (previous contents)
; user's processor status (1 byte)
; user's Data Bank Register (1 byte)
; user's Direct Register (2 bytes)
; top of stack
jsl incbusyflg
sep #$20 ;8-bit mode
lda >statereg ;get current value
sta save_statereg
lda >$E0C08B ;shift in language-card memory
lda >$E0C08B
rep #$20 ;back to 16-bit mode
; Now that we've saved the user's environment, we can get down to the real work
jsr reset_local_mark
sec
lda starting_addr ;build a pointer to the start of the info
sbc #jmp_entry_size-1
sta jmp_tbl_ptr
lda starting_addr+2
sbc #$0000
sta jmp_tbl_ptr+2 ;temp_ptr points to Jump Table Entry
lda [jmp_tbl_ptr] ;get the user ID
sta |USERID ;update the global User ID
jsr find_user_id
bcc @found_it
@do_old_loader
jmp old_loader ;not ExpressLoad's file
@found_it
ldy #ID_Table_Entry.ExpressHandle ;get handle to the ExpressLoad segment
lda [temp_ptr],y
sta ExpressHandle
iny
iny
lda [temp_ptr],y
sta ExpressHandle+2
ldy #JE_FileNum ;check the load file number
lda [jmp_tbl_ptr],y
dec a
bne @do_old_loader ;This file is not ExpressLoad compatible
iny
iny
lda [jmp_tbl_ptr],y ;get the segment we need to find
sta search_seg
iny
iny
lda [jmp_tbl_ptr],y ;get the relative offset
sta jmp_patch_value
iny
iny
lda [jmp_tbl_ptr],y
sta jmp_patch_value+2
jsr merge_path_2
clc
ldy #$0002
lda [ExpressHandle]
adc #ExpressloadSeg.SegCount ;pass the link field
sta HET_ptr ;header entry table pointer
lda [ExpressHandle],y
adc #$0000
sta HET_ptr+2
lda search_seg
dec a ;convert base 1 to base 0
dec a ;allow for ExpressLoad segment
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
;
;Build a pointer to the segment header itself
;
clc
lda HET_entry_ptr ;add in relative address to segment
adc [HET_entry_ptr]
sta seg_header_ptr
lda HET_entry_ptr+2
adc #$0000
sta seg_header_ptr+2
;
;Now lets see if the segment is already loaded into memory
;
ldy #HET_Entry.SegFlags
lda [HET_entry_ptr],y
bpl @new_segment ;we must load the segment from disk
lsr a ;see if the segment is marked as purgable
bcc @its_locked
lda search_seg ;pass in the segment number please
jsr lock_segment ;go and lock this segment
bcs @new_segment ;we have to reload the segment from disk
@its_locked
ldy #HET_Entry.SegHandle ;get the base address
lda [HET_entry_ptr],y
sta temp_handle
iny
iny
lda [HET_entry_ptr],y
sta temp_handle+2
ldy #$0002 ;get the real address
lda [temp_handle]
sta base_ptr
lda [temp_handle],y
sta base_ptr+2
bra @do_patch
@new_segment
jsr open_load_file ;open the puppy
bcc @got_it
@oops
jsr error_routine ;sorry no can do. (No Return)
@got_it
lda #1
sta PSysPrefs.pCount
jsr lock_handles
jsl $e100a8 ;get the current system preferences
dc.w GetSysPrefs
dc.l PSysPrefs
;
;Save the current user's preference please
;
lda PSysPrefs.preferences
sta users_prefs
;
;Now ask the operating system to put up a mount dialog when I ask for a disk
;
lda #$C000 ;ask the OS to put up the mount dialog
sta PSysPrefs.preferences
jsl $e100a8
dc.w SetSysPrefs ;set the system preference
dc.l PSysPrefs
jsr unlock_handles
jsr load_segment ;load the segment into memory
bcs @oops
lda search_seg ;relocate the segment
jsr Process_Reloc
lda users_prefs
sta PSysPrefs.preferences
jsr lock_handles
jsl $e100a8
dc.w SetSysPrefs ;restore the caller's system preference
dc.l PSysPrefs
jsr unlock_handles
jsr close_load_file ;close the file
@do_patch
clc ;add in the offset field
lda base_ptr
adc jmp_patch_value
sta base_ptr
lda base_ptr+2
adc jmp_patch_value+2
sta base_ptr+2
back_to_user
ldy #JE_jsl ;offset to the JSL
lda #$5C ;convert to a JML
sta [jmp_tbl_ptr],y
iny
lda base_ptr
sta [jmp_tbl_ptr],y
sta call_routine+1
lda base_ptr+1
iny
sta [jmp_tbl_ptr],y
sta call_routine+2
;
; Restore user's machine state and jump to the just-loaded routine
;
sep #$20
lda save_statereg ;restore original language card settings
sta >statereg
rep #$20
jsl decbusyflg
pld ;restore Direct Register
lda save_a ;restore registers
ldx save_x
ldy save_y
plb
plp ;restore processor mode
call_routine jml $0000000 ;call the desired routine
old_loader
;
; set System Preferences to Display Mount Dialogs
;
lda #1
sta PSysPrefs.pCount
jsl $E100A8
dc.w GetSysPrefs
dc.l PSysPrefs ;get original preferences
lda PSysPrefs.preferences ;save original preferences
pha
lda #$C000 ;set to show dialog w/o cancel button
sta PSysPrefs.preferences
jsl $E100A8
dc.w SetSysPrefs
dc.l PSysPrefs ;set new preferences
pla
sta PSysPrefs.preferences ;restore original preferences
;
; call Load Dynamic Segment routine
;
lda #0 ;output Address
pha
pha
lda [jmp_tbl_ptr] ;UserID
pha
ldy #JE_FileNum
lda [jmp_tbl_ptr],y ;File Number
pha
ldy #JE_SegNum
lda [jmp_tbl_ptr],y ;Segment Number
pha
jsr Load_Segment
plx
ply
stx TempZero+4 ;address of Dynamic Segment
sty TempZero+6
php ;save carry and error code
pha
;
; restore original System Preferences
;
jsl $E100A8
dc.w SetSysPrefs
dc.l PSysPrefs ;set preferences
pla ;restore error code
plp ;and carry
bcs error ;was there an error?
;
; calculate address of Dynamic Segment function
;
ldy #JE_Offset
lda [jmp_tbl_ptr],y
clc
adc TempZero+4
sta base_ptr
lda TempZero+6
adc #0
sta base_ptr+2
jmp back_to_user ;now off to the routine
error pha ;error code
lda #0 ;no message
pha
pha
_SysFailMgr
ENDP