TITLE ', ExpressLoad.a - Switch_handler' SEG 'Loader' ;==================================================================================================== ;Switch_handler This routine is called when we switch from GS/OS to ProDOS 8 and when we switch ; from ProDOS8 to GS/OS. ; ;Input: 1 = Switch P8 to GS/OS, 0 = Switch GS/OS to P8 ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; The Direct page is saved and released if we are switching from GS/OS to P8 ; The Direct page is allocated and restored if we are switching from P8 to GS/OS ; ;==================================================================================================== longa on longi on Switch_handler proc LoadSegCheck with DirectPage, Globals Import clear_handles, alloc_my_dp function equ 7 lda function,s ;get the input parameter tax ;save in X for a minute lda 5,s ;remove input parameter from stack sta 7,s ;by moving two return addresses up lda 3,s sta 5,s pla sta 1,s phb phk ;set our data bank register plb phd ;save caller's direct page txa ;check the input parameter bne @restore_dp ;goin' back to GS/OS lda Globals.my_dir_page ;setup our own direct page tcd ldx #dir_page_size-2 ;save the direct page please @save_loop lda 00,x sta dir_page_buffer,x dex dex bpl @save_loop lda dp_handle+2 ;dispose the handle pha lda dp_handle pha jsr clear_handles ;clear local copy of handle _DisposeHandle stz dp_handle stz dp_handle+2 bra no_errors @restore_dp jsr alloc_my_dp ;allocate me a direct page please bcs error_exit ;return the error ldx #dir_page_size-2 ;save the direct page please @restore_loop lda dir_page_buffer,x sta 00,x dex dex bpl @restore_loop no_errors lda #0 ;no errors clc error_exit pld ;restore direct page plb ;and DBR rtl endp if 0 then ;nobody likes my special graphics TITLE ', ExpressLoad.a - draw_express' **************************************************************************************************** * * draw_express - draws splash screen text * **************************************************************************************************** draw_express proc LoadSegCheck with DirectPage, Globals line equ $A0 progress_start PointAddress 95,310 my_string_width equ $001a my_string_height equ $0007 sep #$20 ;8-bit accumulator longa off lda >$E0C025 bit #%00000100 ;Caps Lock key down? rep #$20 longa on beq jump_out ;no, just skip it lda #my_string_height sta temp_word ; ;setup pointer to graphics screen area I am going to write to. ; lda #progress_start**$FFFF sta temp_ptr lda #^progress_start sta temp_ptr+2 ldx #$0000 longa off longi on sep #$20 loop1 ldy #$0000 loop lda splash_image,x ;grab graphics line from our buffer sta [temp_ptr],y inx iny cpy #my_string_width ;move one line then update base pointer bne loop clc lda temp_ptr adc #line ;move to the next line sta temp_ptr bcc @1 inc temp_ptr+1 @1 dec temp_word ;see if we have done enough lines bne loop1 longa on longi on rep #$20 jump_out rts ;we are done splash_image HEX FFFFFFFFFFFF03FFFFFFFFFFFF HEX FC0FFFFFFFFFFFF03FFFFFF003 HEX FFFF4444444F03FFFFFFFFFFFF HEX FC0FFFFFFFFFFFF0303FFFC303 HEX FFFFFFFFFFFF03FFF003FC003F HEX 000FC00FC003FFF0303FFF0303 HEX F44444444FFF03FFC0C0F0303C HEX 0C0F0303C03FFFC0303FFF0303 HEX FFFFFFFFFFFC0FFF0303C0C0F0 HEX 303C000F03FFFFC000FFFC0C0F HEX FFFFF4444FFC0FFF0303C0C0F0 HEX 303C0FFF03FFFFFFC0FFFC0C3F HEX FFFFFFFFFFFC000FC00FF000FC HEX 003F003F03FFFFFFC0F03C00FF endp endif TITLE ', ExpressLoad.a - startup' ;==================================================================================================== ;startup: This routine will allocate memory used by the system loader and setup ; any data structures that are used by ExpressLoad. ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ;If this happens I would be suprized ; b = k ; ; ;==================================================================================================== longa on longi on startup proc LoadSegCheck with DirectPage Import alloc_my_dp,add_id_table sep #$20 ;go into 8-bit mode longa off lda >statereg ;get current language card setting pha ;save on stack temporarily lda >$E0C08B ;turn language card on lda >$E0C08B rep #$20 longa on jsr alloc_my_dp ;allocate me a direct page please bcs @error_exit ldx #256 @clear_it dex dex stz DirectPage,x ;zero out my direct page bne @clear_it stz user_id_handle ;indicate that there is no ID table yet stz user_id_handle+2 ; ;Now lets setup one user_id_table ; jsr add_id_table ;add the first User ID Table please @error_exit tax ;save any possible error code sep #$20 ;8-bit accumulator longa off pla ;retrieve saved language card state sta >statereg ;restore it rep #$20 longa on txa ;retrieve possible error code rts ;return the error code to caller endp TITLE ', ExpressLoad.a - get_parameters' ;==================================================================================================== ;get_parameters: This routine is called at the beginning of each Tool call. It will ; get the input parameters off the stack and setup our operating environment. ; ; ;Input: A = undefined ; X = number of paramters on stack ; Y = undefined ; P = nvmxdizc ; ..000... ; b = ? ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on get_parameters proc LoadSegCheck with DirectPage, Globals Import zero_handles,reset_local_mark ; ;Save the data bank register ; phb phb ;save the bank register first pla ; ;Set data bank register to our bank ; phk plb ;set data bank to our bank. sta data_bank ;save caller's DBR ; ;Save the return address ; pla ;save RTS sta local_return ; ;save the app's direct page ; tdc ;save the direct page register sta apps_dir_page ; ;setup our direct page ; lda my_dir_page tcd ;we now have our own direct page ; ;save the return address ; pla ;now save the return address sta return_addr pla ;get both return address off the stack sta return_addr+2 pla sta return_addr+4 phx ;save the # of input parameters jsl incbusyflg ;don't let nobody bother us! ; ; enable the language card memory ; sep #$20 ;8-bit soft-switch access longa off lda >statereg ;get the current setting sta save_statereg lda >$E0C08B ;turn language card on lda >$E0C08B rep #$20 longa on ply ;retrieve the # of input parameters beq @done ;we have done our job ; ;now we need to pull the needed parameters off of the stack. ; ldx #$0000 @loop pla ;get a byte off the stack sta input_parms,x ;save the byte in a common parameter block inx inx dey dey bne @loop @done lda local_return pha jsr zero_handles jsr reset_local_mark stz partial_match ;indicate that we need a complete match!!! rts local_return dc.w 00 endp TITLE ', ExpressLoad.a - return_to_caller' ;==================================================================================================== ;return_to_caller: This routine is called if ExpresssLoad has handled the file ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = no error ; b = K ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ;==================================================================================================== longa on longi on return_to_caller proc LoadSegCheck with DirectPage, Globals Import close_load_file sta local_error lda file_open ;is the load file open? beq @not_open ;the file is not open so don't worry about it. jsr close_load_file ;go ahead and close the file since we are thru with it. @not_open ldy #$0004 ;lets unlock this puppy lda ExpressHandle ora ExpressHandle+2 beq @skip_unlock ;there is no ExpressSegment lda [ExpressHandle],y and #$7FFF ;unlock the handle sta [ExpressHandle],y @skip_unlock sep #$20 ;8-bit soft-switch access longa off lda save_statereg ;get the original setting sta >statereg ;reset rep #$20 longa on jsl decbusyflg ;we be done now lda return_addr+4 pha lda return_addr+2 pha lda return_addr pha lda apps_dir_page tcd ;restore the direct page lda data_bank pha lda local_error plb plb cmp #$0001 rtl local_error dc.w 00 endp TITLE ', ExpressLoad.a - lock_handles' ;==================================================================================================== ;lock_handles This routine will save and lock handles used by ExpressLoad ;unlock_handles This routine will restore the previous state of the now locked handle ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = preserved ; X = preserved ; Y = preserved ; P = preserved ; b = k ; ; ; ;==================================================================================================== longa on longi on lock_handles proc with DirectPage,Globals php ;save all registers! pha phx phy ldy #$0004 ;lets lock this puppy lda ExpressHandle ora ExpressHandle+2 beq @skip_express lda [ExpressHandle],y sta ExpressHndl_flag ora #$8000 ;lock the handle sta [ExpressHandle],y @skip_express lda user_id_handle ;lock ID table down ora user_id_handle+2 beq @skip_ids lda [user_id_handle],y sta user_id_flag ora #$8000 ;lock the handle sta [user_id_handle],y @skip_ids lda temp_handle ora temp_handle+2 beq @skip_temp lda [temp_handle],y sta tempHndl_flag ora #$8000 ;lock the handle sta [temp_handle],y @skip_temp lda reloc_handle ora reloc_handle+2 beq @skip_reloc lda [reloc_handle],y sta relocHndl_flag ora #$8000 ;lock the handle sta [reloc_handle],y @skip_reloc lda seg_handle ora seg_handle+2 beq @skip_seg lda [seg_handle],y sta segHndl_flag ora #$8000 ;lock the handle sta [seg_handle],y @skip_seg lda curr_id_handle ora curr_id_handle+2 beq @skip_id lda [curr_id_handle],y sta idHndl_flag ora #$8000 ;lock the handle sta [curr_id_handle],y @skip_id bra end_handles entry unlock_handles unlock_handles php ;save all registers! pha phx phy ldy #$0004 ;lets lock this puppy lda ExpressHandle ora ExpressHandle+2 beq @skip_express lda ExpressHndl_flag ;restore old state sta [ExpressHandle],y @skip_express lda temp_handle ora temp_handle+2 beq @skip_temp lda tempHndl_flag ;restore original state sta [temp_handle],y @skip_temp lda user_id_handle ;lock ID table down ora user_id_handle+2 beq @skip_ids lda user_id_flag sta [user_id_handle],y @skip_ids lda reloc_handle ora reloc_handle+2 beq @skip_reloc lda relocHndl_flag ;restore orig state sta [reloc_handle],y @skip_reloc lda seg_handle ora seg_handle+2 beq @skip_seg lda segHndl_flag ;do the restore sta [seg_handle],y @skip_seg lda curr_id_handle ora curr_id_handle+2 beq @skip_id lda idHndl_flag ;do the restore sta [curr_id_handle],y @skip_id end_handles ply plx pla plp ;restore original registers rts ExpressHndl_flag dc.w 00 tempHndl_flag dc.w 00 relocHndl_flag dc.w 00 segHndl_flag dc.w 00 idHndl_flag dc.w 00 user_id_flag dc.w 00 endp TITLE ', ExpressLoad.a - clear_handles' ; ; Language card portion of loader starts here ; SEG 'Loader_LC' ;==================================================================================================== ;clear_handles: This routine will zero any local handles that contain a copy of the ; handle that we are disposing ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; stack: ; ; Y register $1,s ; X register $3,s ; Accum $5,s ; processor_status $7,s ; return address $8,s ; low word of handle $A,s ; high word of handle $C,s ; ;Output: A = restored ; X = restored ; Y = restored ; P = nvmxdizc ; ..000... ; b = k ; ; ; ;==================================================================================================== clear_handles proc with DirectPage php pha phx phy lda $0A,s ;get the low word of the handle tax lda $0C,s ;get the high word of the handle cmp ExpressHandle+2 bne @skip_express ;Does Express = Dispose Handle? cpx ExpressHandle bne @skip_express stz ExpressHandle ;zero matching handle stz ExpressHandle+2 @skip_express cmp temp_handle bne @skip_temp cpx temp_handle+2 bne @skip_temp stz temp_handle stz temp_handle+2 @skip_temp cmp reloc_handle bne @skip_reloc cpx reloc_handle+2 bne @skip_reloc stz reloc_handle stz reloc_handle+2 @skip_reloc cmp seg_handle bne @skip_seg cpx seg_handle+2 bne @skip_seg stz seg_handle stz seg_handle+2 @skip_seg cmp curr_id_handle bne @skip_id cpx curr_id_handle+2 bne @skip_id stz curr_id_handle stz curr_id_handle+2 @skip_id ply plx pla plp rts endp TITLE ', ExpressLoad.a - alloc_ExpLoad' ;==================================================================================================== ;alloc_ExpLoad: This routine will allocate memory from the system for the loader. ; ;Input: A = undefined ; X = request bytes low ; Y = requets bytes high ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = handle low ; Y = handle high ; P = nvmxdizc ; ..000.. ; b = k ; ; ;==================================================================================================== longa on longi on alloc_ExpLoad proc with DirectPage, Globals lda #uExpressSegment ;my ID bra do_alloc ;go allocate ;==================================================================================================== ;alloc_mem: This routine will allocate memory from the system. ; ;Input: A = user ID to use ; X = request bytes low ; Y = requets bytes high ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = handle low ; Y = handle high ; P = nvmxdizc ; ..000.. ; b = k ; ; ;==================================================================================================== entry alloc_mem, do_alloc alloc_mem lda |USERID ;use application ID for normal allocation do_alloc pha ;space for handle pha phy ;high request bytes phx ;low request bytes pha ;userID pea attrLocked ;locked lda #0 pha pha jsr lock_handles ;lock my handles so they stay put!! _NewHandle ;allocate the memory jsr unlock_handles ;put the handles back to original state plx ply rts endp TITLE ', ExpressLoad.a - alloc_my_dp' ;==================================================================================================== ;alloc_my_dp: This routine will allocate my direct page from the system. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000.. ; b = k ; ; ;==================================================================================================== longa on longi on alloc_my_dp proc with Globals Import DeRef lda #0 pha ;space for handle pha pha ;request bytes pea 256 pea uDirectPage ;userID pea #attr_locked+attr_bank+attr_page pha ;MUST be in bank 0 pha _NewHandle plx ply ;get the handle stx dp_handle ;save my handle please sty dp_handle+2 bcs @oops txa ;put low word into accumulator jsr DeRef ;get the pointer to the direct page sta my_dir_page tcd ;go ahead and setup the direct register @oops rts ;and return it endp TITLE ', ExpressLoad.a - alloc_LConst_seg' ;==================================================================================================== ;alloc_LConst_seg This routine will allocate memory from the system. ; ;Input: A = undefined ; X = request bytes low ; Y = requets bytes high ; P = nvmxdizc ; ..000... ; b = k ; ; seg_header_ptr ;must be setup ; ;Output: A = undefined ; X = handle low ; Y = handle high ; P = nvmxdizc ; ..000.. ; b = k ; ; ;==================================================================================================== longa on longi on alloc_LConst_seg proc with DirectPage, Globals jsr lock_handles lda mem_attr ;see if this is bank aligned or align in bank and #attr_bank_align+attr_align_in_bank bne @align_to_bank pha ;space for handle pha phy ;high request bytes phx ;low request bytes lda |USERID pha lda mem_attr pha lda org_address+2 pha lda org_address ;address to start at pha _NewHandle jsr unlock_handles ;put the handles back to original state plx ply rts @align_to_bank stx free_mem_size ;save the request count sty free_mem_size+2 lda mem_attr ;clear the align to bank bit and #Ć(attr_bank_align+attr_align_in_bank) sta mem_attr lda #$0002 ;start looking in bank two sta search_addr+2 ;address we are searching for lda org_address ;add in org. align in bank if non zero sta search_addr pha ;space for handle pha ldx #$0000 ;convenient place for a zero pea $0001 ;allocate 64K phx lda |USERID ;use App's ID pha lda mem_attr ;attributes and #Ć(attr_bank+attr_addr) ora #attr_no_spec+attr_no_cross pha phx ;location pointer phx _NewHandle ;allocate the memory plx ;retrieve handle ply bcs @no_memory ;oops! couldn't get a whole bank! phb ;save current DBR phy ;set to handle's DBR plb inx ;bump to bank word of handle inx lda |0,x ;get the bank # that was allocated plb plb ;restore DBR sta search_addr+2 ;save the bank value dex ;restore original value dex phy phx ;now deallocate the bank again _DisposeHandle @no_memory lda #attr_addr+attr_bank ;set the fixed address and bank bits tsb mem_attr @search_loop pha ;space for handle pha lda free_mem_size+2 pha lda free_mem_size pha lda |USERID pha lda mem_attr pha lda search_addr+2 ;address to start at pha lda search_addr pha _NewHandle plx ply ;get the handle bcc @done ;if no error, return! @not_done inc search_addr+2 lda search_addr+2 ;move up one bank cmp #$0080 ;have we searched all of memory? bcc @search_loop lda #$0201 ;synthesize a Memory Manager error ;(carry already set) @done jsr unlock_handles rts ;return the handle endp TITLE ', ExpressLoad.a - add_id_table' ;==================================================================================================== ;add_id_table: This routine will allocate memory for one user_id_table and link the table ; into the list of user_id_tables. It will also zero the entire table ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on add_id_table proc with DirectPage, Globals ldx #id_tbl_size ;allocate the table please ldy #$0000 lda #uUserIDTable ;ID to use for the user id table jsr do_alloc ;go and allocate memory bcs @oops stx temp_handle ;save the handle please stx temp_long sty temp_handle+2 sty temp_long+2 ldy #$0004 ;offset to memory manager attributes lda [temp_handle],y and #$7FFF ;unlock the handle sta [temp_handle],y ldy #$0002 ;make a pointer to new memory lda [temp_handle] sta user_id_ptr lda [temp_handle],y sta user_id_ptr+2 lda #$0000 ldy #id_tbl_size-2 ;clear the buffer please @clear_loop sta [user_id_ptr],y dey dey bpl @clear_loop ; ;Now that we have cleared the segment lets link it into the list ; lda user_id_handle ;see if this is the first one! ora user_id_handle+2 bne @walk_list lda temp_handle ;setup the first handle and exit sta user_id_handle lda temp_handle+2 sta user_id_handle+2 clc @oops rts @walk_list lda user_id_handle ;start at front of the list sta temp_handle lda user_id_handle+2 sta temp_handle+2 @search_loop ldy #$0002 lda [temp_handle] sta user_id_ptr lda [temp_handle],y sta user_id_ptr+2 lda [user_id_ptr] ;get the forward link please (Link = Handle) sta temp_handle lda [user_id_ptr],y sta temp_handle+2 ora temp_handle bne @search_loop ldy #User_ID_Table.Next+2 ;link in the new entry lda temp_long ;handle to our new segment sta [user_id_ptr] lda temp_long+2 sta [user_id_ptr],y lda [temp_long] ;deref handle sta user_id_ptr lda [temp_long],y sta user_id_ptr+2 clc rts endp TITLE ', ExpressLoad.a - reset_local_mark' ;==================================================================================================== ;reset_local_mark: This routine will reset our local mark to $FFFFFF. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = preserved ; X = preserved ; Y = preserved ; P = preserved ; b = k ; ; ; ;==================================================================================================== longa on longi on reset_local_mark proc with DirectPage, Globals lda #$FFFF sta local_mark sta local_mark+2 rts endp TITLE ', ExpressLoad.a - seg_num_lookup' ;==================================================================================================== ;seg_num_lookup: This routine will take a segment number and convert the number ; to the correct segment number via the segment conversion table ; ;Input: A = original segment number ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; HET_ptr ;must point to seg_num_count ; ;Output: A = new segment number ; X = preserved ; Y = preserved ; P = nvmxdizc ; ..000..1=error ; b = k ; ; ; ;==================================================================================================== longa on longi on seg_num_lookup proc with DirectPage, Globals tax beq @bad_seg_num ;sorry bud dec a ;make zero based cmp [HET_ptr] ;is it in the range? beq @num_OK bcs @bad_seg_num ;sorry the segment number is no good @num_OK clc lda [HET_ptr] ;get the number of segments please inc a ;add one for 0 based stuff asl a asl a asl a ;times 8 to pass Header Entry table adc #$0002 ;pass the count please adc HET_ptr ;add current position sta temp_ptr lda #$0000 adc HET_ptr+2 sta temp_ptr+2 ;Temp pointer now points to the segment conv tbl dex ;subtract one for zero based please txa ;Times two for word table asl a tay ;index to the real segment number lda [temp_ptr],y clc rts ;return with the new segment number in "A" @bad_seg_num lda #seg_not_found sec rts ;return the "Error" endp TITLE ', ExpressLoad.a - my_seg_to_user_seg' ;==================================================================================================== ;my_seg_to_user_seg: This routine will take my segment number and convert the number ; to the correct segment number via the segment conversion table. ; This means if you use the segment number returned to you as input ; to another loader call then everything will workout OK. ; ;Input: A = internal segment number ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; HET_ptr ;must point to seg_num_count ; ;Output: A = new segment number for user ; X = preserved ; Y = preserved ; P = nvmxdizc ; ..000..1=error ; b = k ; ; ; ;==================================================================================================== longa on longi on my_seg_to_user_seg proc with DirectPage, Globals pha ;segment we need to find clc lda [HET_ptr] ;get the number of segments please inc a ;add one for 0 based stuff asl a asl a asl a ;times 8 to pass Header Entry table adc #$0002 ;pass the count please ; clc adc HET_ptr ;add current position sta temp_ptr lda #$0000 adc HET_ptr+2 sta temp_ptr+2 ;Temp pointer now points to the segment conv tbl ldy #$0000 pla ;retrieve comparison value @look_loop cmp [temp_ptr],y ;is this the correct segment number? beq @have_segment iny iny bne @look_loop lda #seg_not_found sec rts ;return the "Error" @have_segment tya ;convert index to segment number lsr a inc a ;add one to convert from 0 to 1 based clc rts endp TITLE ', ExpressLoad.a - error_routine' ;==================================================================================================== ;Error_routine: This routine will call the death manager with an error code. The routine will not ; return to the caller. The routine is called with a JSR so I can display the ; address if I want to. ; ;Input: A = error_code ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ; ;==================================================================================================== longa on longi on error_routine proc with DirectPage, Globals pha ;push the error code pea err_string>>16 pea err_string _SysFailMgr brk $ff string pascal err_string dc.b 'ExpressLoad error: ' string asis endp TITLE ', ExpressLoad.a - make_HET_ptr' ;==================================================================================================== ;make_HET_ptr: This routine builds a pointer to the Header Entry Table ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = low word of pointer to Expressload Segment memory ; Y = high word of pointer to Expressload Segment memory ; P = nvmxdizc ; ..000... ; b = k ; ; HET_ptr will point to the segment count field in the Header Entry Table (HET) ; temp_ptr will point to the link field (HET_ptr-4) ; ;==================================================================================================== longa on longi on make_HET_ptr proc with DirectPage, Globals ; ;Setup temp_ptr to point to the reserved field (of Disk Image) of the HET, ; and HET_ptr to point to the segment count field of the segment. ; ldy #$0002 clc lda [ExpressHandle] sta temp_ptr ;temp now points the link field tax clc adc #ExpressloadSeg.SegCount sta HET_ptr ;and HET_ptr points to count field lda [ExpressHandle],y tay sta temp_ptr+2 adc #0 sta HET_ptr+2 rts endp TITLE ', ExpressLoad.a - setup_seg_ptrs' ;==================================================================================================== ;setup_seg_ptrs: This routine builds pointers to the segment header entry and the segment ; ;Input: A = segment number ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; HET_entry_ptr ; seg_header_ptr ; ;==================================================================================================== longa on longi on setup_seg_ptrs proc with DirectPage, Globals dec a ;convert the segment number please 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 rts endp TITLE ', ExpressLoad.a - setup_base_ptr' ;==================================================================================================== ;setup_base_ptr: This routine setups the pointer to the base address of the segment ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; Het_Entry_pointer ;must be setup ; seg_header_ptr ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; base_ptr ; segment_entry ;==================================================================================================== longa on longi on setup_base_ptr proc with DirectPage, Globals import add_segment_offset ldy #HET_Entry.SegHandle ;setup the Base_ptr lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @good_handle txa bne @good_handle sec rts @good_handle stx temp_handle sty temp_handle+2 ;handle to the segment in memory ldy #$0002 ;deref the handle to get the base address lda [temp_handle] tax lda [temp_handle],y tay ora [temp_handle] bne @good_address sec rts @good_address stx base_ptr sty base_ptr+2 ;address of the segment in memory jsr add_segment_offset clc rts endp TITLE ', ExpressLoad.a - alloc_id' ;==================================================================================================== ;alloc_id: This routine will allocate a new user ID for a load file. This routine is called ; by the "initial_Load" routine ; ;Input: A = user_id ;ID from the caller ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = user_id ;ID for the application ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on alloc_id proc with DirectPage, Globals tax and #$00FF bne @exit_alloc ;use the given ID txa and #$FF00 ;see if the Type_ID is 0 bne @get_new ;Use the Input Type and Aux type please txa ora #Application ;set the Type to Application tax @get_new pea $0000 ;space for result phx ;ID stuff _GetNewID plx bcs @oops ;return the error @exit_alloc txa ;set A = user_id sta |USERID ;this is now the Global_ID clc @oops rts endp TITLE ', ExpressLoad.a - compare_paths' ;==================================================================================================== ;compare_paths: This routine will compare the full pathnames pointed to by PathnamePtr and ; TempBuff to see if they are equal. ; It can also compare partial paths if "Partial_Match" is negative. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; PathnamePtr & TempBuff point to the two pathnames to compare ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; .x000..0 = Match found (complete or partial, depending on V flag) ; 1 = Match not found ; 0 = partial match found. ; 1 = complete match found. ; b = k ; ; ;==================================================================================================== longa on longi on compare_paths proc with DirectPage, Globals lda [PathnamePtr] ;compare the string sizes first tay cmp [TempBuff] beq @do_full_check bcc @chk_colon_full_blown ;PathnamePtr contains the smaller string. lda [TempBuff] tay iny ;TempBuff contains the smaller string iny lda [PathnamePtr],y bra @do_chk @chk_colon_full_blown iny iny lda [TempBuff],y @do_chk and #$00FF cmp #seperator ;is it a seperator? bne @not_same @do_partial_compare lda partial_match ;are we looking for a partial match? bpl @not_same ;don't bother. dey longa off sep #$20 @partial_loop lda [PathnamePtr],y ;compare the ascii data eor [TempBuff],y ;case insensitive comparison beq @equal_1 cmp #$20 ;difference only in case? bne @not_same ;nope! lda [PathnamePtr],y ;get character again cmp #'A' ;make sure it's alphabetic bcc @not_same cmp #'Z'+1 bcc @equal_1 cmp #'a' ;lower case? bcc @not_same cmp #'z'+1 bcs @not_same @equal_1 dey bne @partial_loop rep #$61 ;clear overflow & carry bits rts @do_full_check iny ;bump for leading length word longa off sep #$20 @loop lda [PathnamePtr],y ;compare the ascii data eor [TempBuff],y ;case insensitive comparison beq @equal_2 cmp #$20 ;difference only in case? bne @not_same ;nope! lda [PathnamePtr],y ;get character again cmp #'A' ;make sure it's alphabetic bcc @not_same cmp #'Z'+1 bcc @equal_2 cmp #'a' ;lower case? bcc @not_same cmp #'z'+1 bcs @not_same @equal_2 dey bne @loop rep #$21 ;clears carry too sep #$40 ;set overflow bit (full match) rts ;the pathnames are the same @not_same longa on rep #$20 sep #$41 ;no partial or complete match found rts endp TITLE ', ExpressLoad.a - merge_path' ;==================================================================================================== ;merge_path: This routine will merge the volume name and partial path into one complete pathname ; The names are stored at the end of an ExpressLoad segment. ; ;merge_path_2: Alternate entry point that can be used when ExpressHandle already contains the handle. ; ;Input: A = undefined ; X = low word of ExpressHandle ; Y = High Word of ExpressHandle ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000.. ; b = k ; ; PathnamePtr pointer to pathname within ExpressLoad segment ; ;==================================================================================================== longa on longi on merge_path proc entry merge_path_2 with DirectPage, Globals stx ExpressHandle sty ExpressHandle+2 merge_path_2 ldy #$0002 ;build a pointer to ExpressSegment lda [ExpressHandle] sta temp_ptr lda [ExpressHandle],y sta temp_ptr+2 ; ;Now we need to build a pointer to the volume name ; ldy #ExpressloadSeg.PathnameOffset ;offset to the volume name clc lda [temp_ptr],y adc temp_ptr sta PathnamePtr lda #$0000 adc temp_ptr+2 sta PathnamePtr+2 ;PathnamePtr now points to the volume name clc rts endp TITLE ', ExpressLoad.a - add_user_id' ;==================================================================================================== ;add_user_id: This routine will find a empty spot in the user_id table and allocate it ; ;Input: A = user_id ;ID from the caller ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;Output: A = undefined ; X = low word address of entry ; Y = high word address of entry ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on add_user_id proc with DirectPage, Globals sta temp_word ;ID to add ldy #$0002 ;start at the beginning of the user_id table lda [user_id_handle] sta user_id_ptr lda [user_id_handle],y sta user_id_ptr+2 @loop jsr get_free_id ;find a free spot in the table bcc @got_it jsr add_id_table ;add another table please bcc @loop ;try again rts ;return the error @got_it ldx temp_ptr ldy temp_ptr+2 ;address of the entry clc rts get_free_id ldy #id_entry_size ;start at the first available spot ldx #id_entry_cnt ;number of entries in a table @search_loop lda [user_id_ptr],y ;is this avail. beq @its_free clc tya adc #id_entry_size tay dex bpl @search_loop sec rts @its_free clc ;build a pointer to the entry tya adc user_id_ptr sta temp_ptr sta user_id_ptr lda #$000 adc user_id_ptr+2 sta temp_ptr+2 sta user_id_ptr+2 ldy #14 ;clear the entry please (16 bytes total 0 thru 15) lda #$0000 @clr_it sta [temp_ptr],y dey dey bpl @clr_it lda temp_word ;save the user Id please sta [temp_ptr] clc rts endp TITLE ', ExpressLoad.a - delete_user_id' ;==================================================================================================== ;delete_user_id: This routine will delete the user_id pointer to by user_id ; ;Input: A = user_id_Flag: 0 = delete ID, 1 = keep the user_id ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; user_id ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on delete_user_id proc with DirectPage, Globals sta id_flag ;used to determine if I should delete the user id ldy #ID_Table_Entry.ExpressHandle lda [user_id_ptr],y ;get the ExpressLoad handle tax iny iny lda [user_id_ptr],y tay bne @deallocate tax beq @no_handle @deallocate phy phx jsr clear_handles ;clear local copy of handle _DisposeHandle @no_handle lda [user_id_ptr] ;get the user_id beq @zero_and_exit pha ;ID to nuke _DisposeAll ldx id_flag ;should we nuke the ID? bne @zero_and_exit ;no... lda [user_id_ptr] ;get the user_id pha ;ID to nuke _DeleteID @zero_and_exit ldy #$0002 lda #$0000 sta [user_id_ptr] sta [user_id_ptr],y iny iny sta [user_id_ptr],y ;remove everything stz ExpressHandle ;indicate that we no longer have the load file stz ExpressHandle+2 clc rts endp TITLE ', ExpressLoad.a - purge_user_id' ;==================================================================================================== ;purge_user_id: This routine will mark an application as purgable ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; user_id ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on purge_user_id proc with DirectPage, Globals lda [user_id_ptr] ;get the user_id beq @exit pha _PurgeAll @exit rts endp TITLE ', ExpressLoad.a - remove_segment' ;==================================================================================================== ;remove_segment: This routine will deallocate all memory associated with a user ID. ; ;Input: A = And Mask for flags field ; X = Compare Value ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ExpressHandle ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on remove_segment proc with DirectPage, Globals sta temp_word stx search_kind jsr make_HET_ptr lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_remove ;sorry there is no segment phx jsr setup_seg_ptrs ;we are now in business ldy #HET_Entry.SegFlags lda [HET_entry_ptr],y and temp_word ;AND off user requested bits cmp search_kind ;see if we have a match bne @skip_it jsr do_operation @skip_it plx dex ;back off by one and try again cpx #$0001 bne @search_loop @end_remove clc rts do_operation lda #$0000 ;zero the status word sta [HET_entry_ptr],y ldy #HET_Entry.SegHandle ;lets dispose of the handle please lda [HET_entry_ptr],y tax lda #$0000 sta [HET_entry_ptr],y iny iny lda [HET_entry_ptr],y ;get the high word pha lda #$000 sta [HET_entry_ptr],y phx ;push the low word jsr clear_handles ;clear local copy of handle _DisposeHandle rts endp TITLE ', ExpressLoad.a - find_user_id' ;==================================================================================================== ;find_user_id: This routine will find a user_id in the user_id_Table ; ;Input: A = user_id ;ID from the caller ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = low word address of entry ; Y = high word address of entry ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on find_user_id proc with DirectPage, Globals tax bne @use_input lda |USERID ;use the global ID @use_input sta search_kind sta |USERID ;update the global User ID ldy #$0002 lda [user_id_handle] sta user_id_ptr lda [user_id_handle],y sta user_id_ptr+2 @loop jsr find_id bcc @found_it ldy #User_ID_Table.Next+2 ;get the next link lda [user_id_ptr] tax lda [user_id_ptr],y tay bne @keep_going txa bne @keep_going sec rts ;sorry ID not found @keep_going stx temp_handle stx curr_id_handle ;the current handle table sty temp_handle+2 sty curr_id_handle+2 ldy #$0002 lda [temp_handle] sta user_id_ptr lda [temp_handle],y sta user_id_ptr+2 bra @loop @found_it ldx temp_ptr ;return pointer to the entry ldy temp_ptr+2 clc rts find_id ldy #id_entry_size ;start at the first available spot ldx #id_entry_cnt ;number of entries in a table @search_loop lda [user_id_ptr],y ;is this the one cmp search_kind beq @its_the_one clc tya adc #id_entry_size tay dex bpl @search_loop sec rts @its_the_one clc ;build a pointer to the entry tya adc user_id_ptr sta temp_ptr sta user_id_ptr lda #$000 adc user_id_ptr+2 sta temp_ptr+2 sta user_id_ptr+2 clc rts endp TITLE ', ExpressLoad.a - path_to_user_id' ;==================================================================================================== ;path_to_user_id: This routine will find a user_id in the user_id_Table given a pathname ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; TempBuff ;pointer to path that we need to find ; ;Output: A = User ID ; X = undefined ; Y =undefined ; P = nvmxdizc ; ..000..1 = not found ; b = k ; ; ;==================================================================================================== longa on longi on path_to_user_id proc with DirectPage, Globals ldy #$0002 lda [user_id_handle] sta user_id_ptr lda [user_id_handle],y sta user_id_ptr+2 @loop jsr find_id bcc @found_it ;we have found the complete path! ldy #$0002 ;get the next link lda [user_id_ptr] tax lda [user_id_ptr],y tay ora [user_id_ptr] bne @keep_going sec rts ;sorry ID not found @keep_going stx temp_handle sty temp_handle+2 ldy #$00002 lda [temp_handle] sta user_id_ptr lda [temp_handle],y sta user_id_ptr+2 bra @loop @found_it rts ;A = user_id find_id ldy #id_entry_size ;start at the first available spot ldx #id_entry_cnt ;number of entries in a table @search_loop lda [user_id_ptr],y ;is this the one sta search_kind ;save the User ID beq @empty_slot phy phx jsr check_name ;is this the one plx ply bcc @its_the_one @empty_slot clc tya adc #id_entry_size tay dex bpl @search_loop sec sep #$40 ;no partial match!!! @its_the_one rts check_name iny iny ;get the handle lda [user_id_ptr],y tax iny iny lda [user_id_ptr],y tay jsr merge_path ;build a complete pathname jsr compare_paths ;is this the one? lda search_kind rts ;carry set or cleared from the compare routine endp TITLE ', ExpressLoad.a - find_seg_handle' ;==================================================================================================== ;find_seg_handle: This routine will find a segment by handle ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; seg_handle ;must be setup ; ;Output: A = User ID ; X = undefined ; Y =undefined ; P = nvmxdizc ; ..000..1 = not found ; b = k ; ; ;==================================================================================================== longa on longi on find_seg_handle proc with DirectPage, Globals ldy #$0002 lda [user_id_handle] sta user_id_ptr lda [user_id_handle],y sta user_id_ptr+2 @loop jsr find_id bcc @found_it ldy #User_ID_Table.Next+2 ;get the next link lda [user_id_ptr] tax lda [user_id_ptr],y tay bne @keep_going txa bne @keep_going sec rts ;sorry ID not found @keep_going stx temp_handle sty temp_handle+2 ldy #$00002 lda [temp_handle] sta user_id_ptr lda [temp_handle],y sta user_id_ptr+2 bra @loop @found_it rts ;A = user_id find_id ldy #id_entry_size ;start at the first available spot ldx #id_entry_cnt ;number of entries in a table @search_loop lda [user_id_ptr],y ;is this the one sta |USERID beq @empty_slot phy phx jsr check_handle ;is this the one plx ply bcc @its_the_one @empty_slot clc tya adc #id_entry_size tay dex bpl @search_loop sec @its_the_one sta search_seg ;save the segment number rts check_handle iny iny ;get the handle lda [user_id_ptr],y sta ExpressHandle tax iny iny lda [user_id_ptr],y sta ExpressHandle+2 ;Handle to the ExpressLoad segment jsr walk_expressSeg ;look at all the handles in the ExpressLoad segment rts ;found the handle walk_expressSeg jsr make_HET_ptr ;make a pointer to the Header Entry Table lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_handle ;sorry there is no segment by this name phx jsr setup_seg_ptrs ;we are now in business ldy #HET_Entry.SegHandle ;see if this is a jump segment lda [HET_entry_ptr],y cmp seg_handle bne @not_handle iny iny lda [HET_entry_ptr],y cmp seg_handle+2 bne @not_handle pla ;this is the segment number clc rts @not_handle plx dex ;back off by one and try again cpx #$0001 bne @search_loop @end_handle sec rts endp TITLE ', ExpressLoad.a - get_seg_base' ;==================================================================================================== ;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 = undefined ; ; 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 DirectPage dec a ;HET table numbers are 0 thru (-n- minus 1) 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 ; ;Now we need to setup our Base address for this segment ; ldy #HET_Entry.SegHandle ;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 TITLE ', ExpressLoad.a - Process_Reloc' ;==================================================================================================== ;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 DirectPage, Globals ; sta reloc_seg ;segment numbers are 1 thru -n- jsr setup_seg_ptrs ;build pointers to the segment entries ; ;Now we need to setup our Base address for this segment ; ldy #HET_Entry.SegHandle ;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 #SegHeaderEntry.RelocDict_Length ;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 #SegHeaderEntry.RelocDict_Hndl ;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 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 cmp #$00E2 ;valid record? bcc @invalid_record ;no... cmp #$F8 bcc @good_record @invalid_record lda #$00E4 ;translate into another invalid number @good_record 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 ldy #SegHeaderEntry.RelocDict_Hndl+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 _DisposeHandle 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 TITLE ', ExpressLoad.a - Reloc_handler' ;==================================================================================================== ; ;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 TITLE ', ExpressLoad.a - cReloc_handler' ;==================================================================================================== ; ;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 TITLE ', ExpressLoad.a - Interseg_handler' ;==================================================================================================== ; ;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 TITLE ', ExpressLoad.a - cInterseg_handler' ;==================================================================================================== ; ;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 TITLE ', ExpressLoad.a - super_handler' ;==================================================================================================== ;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 TITLE ', ExpressLoad.a - Interseg_1' ;==================================================================================================== ;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 TITLE ', ExpressLoad.a - Interseg_14' ;==================================================================================================== ;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 TITLE ', ExpressLoad.a - Interseg_26' ;==================================================================================================== ;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 TITLE ', ExpressLoad.a - reloc2' ;==================================================================================================== 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 TITLE ', ExpressLoad.a - reloc3' ;==================================================================================================== 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 TITLE ', ExpressLoad.a - shift_patch' ;==================================================================================================== ; ;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 TITLE ', ExpressLoad.a - read_less_64k' ;==================================================================================================== ;read_less_64K: This routine will read data from the input file. It is limited to $FFFF bytes ; ; ;Input: A = request count ; X = buffer_ptr low ; Y = buffer_ptr high ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on read_less_64k proc with DirectPage, Globals stz |PRead.requestCount+2 sta |PRead.requestCount export read_wBuf_ptr read_wBuf_ptr stx |PRead.dataBuffer sty |PRead.dataBuffer+2 jsr lock_handles jsl $e100a8 dc.w PD_READ ;class 0 read call dc.l PRead jsr unlock_handles bcs @exit lda |PRead.transferCount adc local_mark ;bump the local mark please sta local_mark lda |PRead.transferCount+2 adc local_mark+2 sta local_mark+2 lda #$0000 clc @exit rts endp TITLE ', ExpressLoad.a - set_mark' ;==================================================================================================== ;set_mark: This routine will set the current file position ; ; ;Input: A = undefined ; X = displacement low ; Y = displacement high ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = error if carry set ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on set_mark proc with DirectPage, Globals stx |PSetMark.position sty |PSetMark.position+2 cpx local_mark ;lets see if we are already at the mark bne @do_mark cpy local_mark+2 bne @do_mark clc lda #$0000 ;we are already at the mark rts ;return with no error @do_mark jsr lock_handles jsl $e100a8 dc.w SET_MARK ;class 0 set mark call dc.l PSetMark jsr unlock_handles bcs @exit lda |PSetMark.position sta local_mark ;reset our mark please lda |PSetMark.position+2 sta local_mark+2 @exit rts endp TITLE ', ExpressLoad.a - check_express_seg' ;==================================================================================================== ;check_express_seg: This routine will determine if this is an expressload file ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; PathnamePtr pointer to file's pathname ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on check_express_seg proc with DirectPage, Globals ldx #Header ldy #^Header lda #SegmentHeader.SegHeaderSize ;read in segment header jsr read_less_64k ;read in less then 64K bcs @oops @no_error lda |PRead.transferCount ;is the segment > $47 bytes cmp #SegmentHeader.SegHeaderSize beq @good_size sec @oops rts ;return with error flag @good_size lda Header.DispName ;offset to the name clc adc #10 ;pass my Name clc adc #Header sta temp_ptr lda #^Header sta temp_ptr+2 ;point to the name field longa off longi off sep #$30 lda [temp_ptr] ;get the length of the name cmp express_name ;is the length the same? bne next_name ;cannot be the same tay @loop lda [temp_ptr],y cmp #'a' ;is this lower case bcc @not_lower cmp #'z'+1 bcs @not_lower and #$DF ;convert to Upper case @not_lower cmp express_name,y bne sorry_not_express dey bne @loop ;keep checking bra load_it ; ;Now look for "~ExpressLoad" ; next_name cmp tilda_name ;now check for "~ExpressLoad" bne sorry_not_express tay @loop lda [temp_ptr],y cmp #'a' ;is this lower case bcc @not_lower cmp #'z'+1 bcs @not_lower and #$DF ;convert to Upper case @not_lower cmp tilda_name,y bne sorry_not_express dey bne @loop ;keep checking load_it rep #$30 clc rts sorry_not_express longa on longi on rep #$30 sec rts endp TITLE ', ExpressLoad.a - find_Segment' ;==================================================================================================== ;find_Segment: This routine will search for segments in the HET table ; ; ;Input: A = Kind to search for ; X = AND mask for kind field. If equal after AND the kind was a match ; Y = AND mask for flags field. If equal after AND then search succeeds ; P = nvmxdizc ; ..000... ; b = k ; ; HET_ptr ;must be setup! ; ;Output: A = Segment number in file ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = not found ; b = k ; ; ;==================================================================================================== longa on longi on find_Segment proc with DirectPage, Globals sta search_kind stx kind_mask sty flags_mask ldx #$0000 ;start search from the beginning @loop txa asl a asl a asl a ;times eight for HET inc a inc a ;pass the count word tay clc adc HET_ptr sta HET_entry_ptr ;build a pointer to the HET entry lda #$0000 adc HET_ptr+2 sta HET_entry_ptr+2 clc lda [HET_entry_ptr] ;get the relative offset to segment adc HET_entry_ptr sta seg_header_ptr ;point to the segment lda #$0000 adc HET_entry_ptr+2 sta seg_header_ptr+2 iny iny lda [HET_ptr],y ;check the flags mask and flags_mask bne @check_next ;sorry ldy #SegHeaderEntry.Kind ;lets check the kind please lda [seg_header_ptr],y and kind_mask cmp search_kind ;is this it bne @check_next ;sorry false alarm txa inc a ;convert 0 thru n to 1 thru n inc a ;account for ExpressLoad segment sta loaded_seg_num clc rts ;return the segment @check_next inx txa cmp [HET_ptr] ;are we done beq @loop ;we have one more to do bcc @loop rts ;return with the carry set endp TITLE ', ExpressLoad.a - chk_dynamic_seg' ;==================================================================================================== ;chk_dynamic_seg: See if there are any dynamic segments in the file. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;handle to the express segment. ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = no seg. ; b = k ; ; ;==================================================================================================== longa on longi on chk_dynamic_seg proc with DirectPage, Globals jsr make_HET_ptr ;setup pointer to the HETable lda #dynamic ;Compare to Dynamic BIT tax ;And Mask (Only Dynamic Bit is important) ldy #unloaded_state ;only unloaded segments please jsr find_Segment ;do the search rts endp TITLE ', ExpressLoad.a - save_ref_num' ;==================================================================================================== ;save_ref_num: This routine will save the files reference number if the file contains any dynamic ; segments. We do this so the file can remain open while the program is running. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; POpen.refNum ;reference number for the current file. ; ExpressHandle ;handle to the express segment. ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on save_ref_num proc with DirectPage, Globals lda |POpen.fileType ;retrieve returned file type cmp #app_type ;only leave the file open if type = Application bne @skip_dynamic_chk ;don't leave the file open jsr chk_dynamic_seg bcc @save_the_num ;There is a dynamic segment. @skip_dynamic_chk clc rts @save_the_num ldy #$0002 clc lda [ExpressHandle] sta temp_ptr ;temp now points the link field lda [ExpressHandle],y sta temp_ptr+2 lda |POpen.refNum ;save the file reference number since the file sta [temp_ptr] ; contains Dynamic Segments. rts endp TITLE ', ExpressLoad.a - get_express_seg' ;==================================================================================================== ;get_express_seg: This routine will locate and read in the ExpressLoad Header ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; PathnamePtr points to pathname ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on get_express_seg proc with DirectPage, Globals clc lda Header.DispData adc #$0005 ;Add in LConst overhead tax ldy #$0000 jsr set_mark bcs @error_return ldx Header.Length ;get the size of the disk image please stx |PRead.requestCount ldy Header.Length+2 sty |PRead.requestCount+2 ; ;Now we need to add in the pathname overhead + mod date field overhead ; lda [PathnamePtr] ;get the length of the pathname clc adc #10 ;add 2 (for length word) and 8 (for mod date) clc adc Header.Length ;add in ExpressLoad segment size tax ;save request count low lda #$0000 adc Header.Length+2 tay ;save request count high jsr alloc_ExpLoad ;get enough memory to hold segment bcs @error_return stx ExpressHandle ;handle to Express Segment stx temp_handle sty ExpressHandle+2 sty temp_handle+2 ldy #$0002 lda [temp_handle] ;clear the link field etc. sta base_ptr lda [temp_handle],y sta base_ptr+2 ; ;Lets go ahead and add the Express Segment into the User ID table ; lda |USERID ;this is the ID to use jsr add_user_id ;temp_ptr setup by Add_user_id bcs @error_return ldy #ID_Table_Entry.ExpressHandle ;save the Handle to the ExpressSegment lda ExpressHandle sta [temp_ptr],y iny iny lda ExpressHandle+2 sta [temp_ptr],y jsr make_HET_ptr ;temp_ptr will point to the link field (HET_ptr-4) jsr read_wBuf_ptr ;make the read call please bcs @error_return ldx temp_ptr ;pass in pointer to ExpressSegment link field ldy temp_ptr+2 jsr store_pathname ;store the pathname in the ExpressLoad segment jsr save_ref_num ;save the files reference number. clc @error_return rts TITLE ', ExpressLoad.a - store_pathname' ;==================================================================================================== ; ;This routine will add in the pathname stored at [PathnamePtr] to the ExpressLoad segment. ; ;Input: A = undefined ; X = Points to the ExpressLoad segment link field ; Y = Points to the ExpressLoad segment link field ; P = nvmxdizc ; ..000... ; b = k ; ; PathnamePtr pointer to pathname ; base_ptr pointer to ExpressLoad segment ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ;Uses: ; ;==================================================================================================== store_pathname clc txa adc |PRead.requestCount ;build a pointer to the Volume Name Buffer sta super_ptr ;another temp pointer tya adc |PRead.requestCount+2 sta super_ptr+2 ;super_ptr now points past the ExpressLoad segment ldy #6 ;copy 8 bytes @store_date_loop lda POpen.modDateTime,y sta [super_ptr],y dey dey bpl @store_date_loop lda super_ptr ;update super_ptr to location for pathname clc adc #8 sta super_ptr bcc @no_bump inc super_ptr+2 @no_bump lda [PathnamePtr] ;get the length sta [super_ptr] ;and store in destination inc a ;bump by 1 for leading length word tay ;into indexor sep #$20 ;8-bit mode longa off @store_name_loop lda [PathnamePtr],y ;copy characters from source sta [super_ptr],y ;to destination dey ;continue until back at length word bne @store_name_loop rep #$20 ;back to 16-bit accumulator longa on ldy #ExpressloadSeg.PathnameOffset ;index to offset field (relative offset is based sec ;from the beginning of the segment) lda super_ptr sbc base_ptr sta [base_ptr],y rts endp TITLE ', ExpressLoad.a - close_dynamic_file' ;==================================================================================================== ;close_dynamic_file: This routine will close the load file if the file is still open ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error if any ; b = k ; ; ;==================================================================================================== longa on longi on close_dynamic_file proc with DirectPage, Globals import close_load_file pei temp_ptr ;save temp pointer please pei temp_ptr+2 ldy #$0002 clc lda [ExpressHandle] sta temp_ptr ;temp now points the link field lda [ExpressHandle],y sta temp_ptr+2 lda [temp_ptr] ;see if there is reference number. beq @exit ;no, just exit with Acc = 0 sta |POpen.refNum ;setup the reference number for closing lda #$0000 ;zero the reference number in ExpressSegment sta [temp_ptr] inc a ;set the pCount 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 close_load_file ;close the file please 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 @exit plx stx temp_ptr+2 plx stx temp_ptr cmp #$0001 rts ;exit with error if any endp TITLE ', ExpressLoad.a - close_load_file' ;==================================================================================================== ;close_load_file: This routine will close the load file and restore the caller's sys_prefs ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error if any ; b = k ; ; ;==================================================================================================== longa on longi on close_load_file proc with DirectPage, Globals lda ExpressHandle ;see if there is an ExpressSegment for this file. ora ExpressHandle+2 beq @do_close ;There is no Segment associated with the file. ldy #$0002 clc lda [ExpressHandle] sta temp_ptr ;temp now points the reference number field lda [ExpressHandle],y sta temp_ptr+2 lda [temp_ptr] ;see if there is reference number. beq @do_close ;there is no reference number with the segment so ;go ahead and close the file they want. lda #$0000 clc bra @do_preference ;No error and I am not going to close the file ;since the file contains Dynamic Segments I will ;leave the file open. @do_close lda POpen.refNum ;is there a valid refNum? beq @do_preference ;no, so don't do a global close jsr lock_handles jsl $e100a8 dc.w PD_CLOSE ;GS/OS close command dc.l POpen.refNum jsr unlock_handles ; ;Save the error code and statue from the close call while I restore the user's system preferences ; @do_preference pha php stz file_open ;file is now closed jsr reset_local_mark ;our local mark is invalid plp pla ;restore the close error if any rts endp TITLE ', ExpressLoad.a - open_load_file' ;==================================================================================================== ;Open_load_file: This routine will open the load file and verify the storage type ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; pathname pointer must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on open_load_file proc with DirectPage, Globals ; ;Now before I open the file let me see If I have a Reference number for it already. ; lda ExpressHandle ;see if there is an ExpressSegment for this file. ora ExpressHandle+2 beq @do_open ;There is no Segment associated with the file. ; ;There is an Active Segment so lets see if we have the reference number ; ldy #$0002 clc lda [ExpressHandle] sta temp_ptr ;temp now points the reference number field lda [ExpressHandle],y sta temp_ptr+2 lda [temp_ptr] ;see if there is reference number. beq @do_open ;There is no reference number so lets open the file sta |POpen.refNum ;save the reference number lda #app_type ;setup the file type also sta |POpen.fileType brl @opened ;say that we already opened the file. @get_pathname @do_open lda #10 ;pCount (return info up to OptionList) sta |POpen.pCount lda #$01 ;requestAccess sta |POpen.requestAccess sta PSysPrefs.pCount inc a sta PGetLevel.pCount sta PSetLevel.pCount stz PGetLevel.levelMode stz PSetLevel.levelMode stz POpen.resourceNumber ;resourceNumber (data fork always) lda PathnamePtr ;address of GString sta |POpen.pathname lda PathnamePtr+2 ;address of GString sta |POpen.pathname+2 ;setup the Open Parameter block 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 jsl $e100a8 ;do a get level call to get the current level dc.w GetLevel dc.l PGetLevel ;get the level lda #my_level sta PSetLevel.level jsl $e100a8 dc.w SetLevel ;set the current level dc.l PSetLevel jsl $e100a8 ;call GS/OS dc.w Open ;class 1 open call dc.l POpen pha php jsl $e100a8 ;set back to user's setting dc.w SetLevel ;set the current level dc.l PGetLevel ;(just reuse this parm block) lda users_prefs sta PSysPrefs.preferences jsl $e100a8 dc.w SetSysPrefs ;restore the caller's system preference dc.l PSysPrefs jsr unlock_handles plp pla bcs @oops ;return the error to the caller @opened stz local_mark stz local_mark+2 ;we are at the beginning of the file. lda |POpen.refNum ;setup the reference number sta |PRead.fileRefNum sta |PGetMark.markRefNum sta |PSetMark.markRefNum lda #$0001 ;indicate that the file is open sta file_open *** added 18-Aug-92 DAL -- allow file types $003x lda |POpen.fileType and #$FFF0 cmp #$0030 beq @chk_length *** end 18-Aug-92 lda |POpen.fileType ;get returned filetype cmp #Load_File bcc @no_way cmp #Last_Load_File+1 ;max file type that we support bcc @chk_length cmp #$C7 ;is it a CDev file? bne @no_way ;nope, can't be a load file @chk_length jsr lock_handles ;lock the handles around the OS call jsl $E100A8 ;Call GS/OS dc.w GET_EOF ; GetEOF dc.l PGetMark jsr unlock_handles bcs @oops lda |PGetMark.position ;is there anything in the file? ora |PGetMark.position+2 bne @oops ;actually no error @no_way lda #not_load_file ;Incompatible file format sec @oops rts ;return error endp TITLE ', ExpressLoad.a - conv_attributes' ;==================================================================================================== ;conv_attributes: This routine will convert the attributes in the segment header to ; memory manager attributes ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; seg_header_ptr ;must be setup ; ;Output: A = Memory Manager Attributes ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== mm_attr_tbl record ;attr_locked 1 = segment is locked when allocated ;attr_fixed 1 = segment can't move while it is in memory ;attr_no_cross 1 = segment may not cross a bank boundary ;attr_no_spec 1 = segment may not use special memory ;attr_page 1 = segment will be page aligned ;attr_addr 1 = segment will remain at fixed address ;attr_bank 1 = segment must remain in fixed bank dc.w attr_locked+attr_fixed+attr_no_cross dc.w attr_locked+attr_fixed+attr_no_cross+attr_bank dc.w attr_locked+attr_fixed+attr_no_cross+attr_no_spec dc.w attr_locked+attr_fixed+attr_no_cross+attr_no_spec+attr_bank dc.w attr_locked+attr_no_cross dc.w attr_locked+attr_no_cross+attr_bank dc.w attr_locked+attr_no_cross+attr_no_spec dc.w attr_locked+attr_no_cross+attr_no_spec+attr_bank dc.w attr_locked+attr_fixed dc.w attr_locked+attr_fixed+attr_bank dc.w attr_locked+attr_fixed+attr_no_spec dc.w attr_locked+attr_fixed+attr_no_spec+attr_bank dc.w attr_locked dc.w attr_locked+attr_bank dc.w attr_locked+attr_no_spec dc.w attr_locked+attr_no_spec+attr_bank endr longa on longi on conv_attributes proc with DirectPage, Globals ldy #SegHeaderEntry.Kind ;get the segment kind lda [seg_header_ptr],y sta seg_kind ;save the word for later xba ;get the segment attributes lsr a lsr a lsr a ;move abs. bank, special mem, and pos. independent and #$0007 ;clear other garbage sta mm_attr ;save temporarily ; ;If the bank size = $10000 then we must set the no_cross bit in the attribute ; ldx #$0008 ;default is can cross ldy #SegHeaderEntry.BankSize ;get the bank size please lda [seg_header_ptr],y bne @can_cross ;it must be able to cross iny iny lda [seg_header_ptr],y ;get the high please beq @can_cross ;we can cross bank boundaries ldx #$0000 ; ;now we get the memory manager attributes ; ; We have now handled the following bits: ; ; (1) absolute Bank ; (2) special Memory ; (3) position independent ; (4) bank crossing ; @can_cross txa ora mm_attr asl a tax lda mm_attr_tbl,x ;get the correct atributes for memory manager ; ;We still need to handle the following things: ; ; (1) Purge Level (3 for dynamics) ; (2) Alignment (page and Bank) ; (3) Org (fixed address) ldx seg_kind bpl @its_static ;this is a static segment ora #purge_level_3 ;set the purge level to three for dynamics @its_static sta mm_attr ldx #attr_page ;default is page aligned ldy #SegHeaderEntry.Align ;offset to the alignment field lda [seg_header_ptr],y beq @align_high cmp #257 bcc @set_aligned ;align to a page boundary ldx #attr_bank_align ;force bank alignment bra @set_aligned @align_high iny iny ldx #attr_bank_align ;force bank alignment lda [seg_header_ptr],y beq @do_org ;there is no alignment @set_aligned txa tsb mm_attr ;add in the alignment bit @do_org ldy #SegHeaderEntry.Org ;offset to segment org lda [seg_header_ptr],y sta org_address iny iny lda [seg_header_ptr],y sta org_address+2 ora org_address beq @no_org lda org_address ;if the low byte is non-zero then fixed attr = true bne @do_fixed_addr lda seg_kind ;see if this is a absolute bank segment and #kind_abs_bank bne @no_org ;This is absolute bank but not fixed address @do_fixed_addr lda #attr_addr ;block must remain at fixed addr tsb mm_attr @no_org lda seg_kind ;see if this is an absolute Bank only tay and #kind_bank_bit ;see if this segment is aligned in any bank beq @not_aligned_in_bank lda #attr_align_in_bank tsb mm_attr ;segment is aligned within the bank ; ;Now we need to handle the direct page / stack segment ; @not_aligned_in_bank tya bit #kind_abs_bank ;absolute bank segment? bne @is_abs ;yes, allow special memory and #kind_only ;clear attributes cmp #dp_seg_type ;DP/Stack segment? bne @no_stack ;no, conditionalize special memory bit lda mm_attr ora #attr_page+attr_bank ;fixed bank and page aligned ; sta mm_attr rts ;skip special memory flag @is_abs lda mm_attr ;must return attributes in accumulator and #Ćattr_no_spec ; sta mm_attr rts @no_stack lda mm_attr ldx spec_mem_flag ;check the special memory flag beq @skip_spec ora #attr_no_spec ;sorry bud no special memory for you ; sta mm_attr @skip_spec rts endp TITLE ', ExpressLoad.a - reset_jmp_tables' ;==================================================================================================== ;reset_jmp_tables: This routine will mark all jump table segments as unloaded for a given ; user id ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on reset_jmp_tables proc with DirectPage, Globals lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_reset ;sorry there is no segment by this name phx jsr setup_seg_ptrs ;we are now in business ldy #HET_Entry.SegFlags ;see if this is a jump segment lda [HET_entry_ptr],y and #jmp_type beq @not_jump jsr clr_table ;clear this segment @not_jump plx dex ;back off by one and try again cpx #$0001 bne @search_loop @end_reset clc rts clr_table ldy #HET_Entry.SegHandle lda [HET_entry_ptr],y sta temp_handle iny iny lda [HET_entry_ptr],y sta temp_handle+2 ldy #$0002 ;point to the first entry in table clc lda [temp_handle] adc #seg_jmp_start sta temp_ptr lda [temp_handle],y adc #$0000 sta temp_ptr+2 @loop ldy #JE_FileNum ;see if we are done lda [temp_ptr],y beq @done lda |USERID ;see if this is the user ID cmp [temp_ptr] bne @next_entry ldy #JE_jsl ;index to the JSL instruction lda jump_load_instr ;store the Jump Load Instruction sta [temp_ptr],y iny iny lda jump_load_instr+2 sta [temp_ptr],y @next_entry clc lda temp_ptr adc #jmp_entry_size ;size of one entry sta temp_ptr lda temp_ptr+2 adc #$0000 sta temp_ptr+2 bra @loop @done rts endp TITLE ', ExpressLoad.a - make_purgable' ;==================================================================================================== ;make_purgable: This routine will make segment purgable and unlocked ; ; ;Input: A = segment_number ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on make_purgable proc with DirectPage, Globals sta search_seg ;segment we need to nuke jsr make_HET_ptr lda search_seg jsr setup_seg_ptrs ;point to the entry please ldy #HET_Entry.SegFlags ;see of it is loaded lda [HET_entry_ptr],y bmi @do_it @no_seg lda #seg_not_found ;seg_not_found sec rts @do_it ldy #HET_Entry.SegHandle ;lets get the handle lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @have_handle txa beq @no_seg @have_handle pea $0003 ;make it purgable phy phx ;push the handle stx temp_handle sty temp_handle+2 ;handle to the segment ldy #$0004 ;lets unlock this puppy lda [temp_handle],y and #$7FFF sta [temp_handle],y ldy #HET_Entry.SegFlags ;mark this segment as Purgable lda [HET_entry_ptr],y ora #$0001 sta [HET_entry_ptr],y ;segment is now marked purgable jsr reset_jmp_tables ;go and reset the jump tables for this ID _SetPurge rts ;return any error endp TITLE ', ExpressLoad.a - purge_all_dyn' ;==================================================================================================== ;purge_all_dyn: This routine will mark all dynamic segments as purgable ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on purge_all_dyn proc with DirectPage, Globals lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_purge ;sorry there is no segment phx jsr setup_seg_ptrs ;we are now in business ldy #SegHeaderEntry.Kind ;lets check the kind please lda [seg_header_ptr],y bpl @skip_it ;skip the segment if it is not dynamic ldy #HET_Entry.SegFlags ;mark this segment as Purgable lda [HET_entry_ptr],y bpl @skip_it ;the segment is already unloaded lda 1,s ;get the seg number jsr make_purgable @skip_it plx dex ;back off by one and try again cpx #$0001 bne @search_loop @end_purge clc rts endp TITLE ', ExpressLoad.a - mark_all_purgable' ;==================================================================================================== ;mark_all_purgable: This routine will mark all segments as purgable ; ; ;Input: A =undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on mark_all_purgable proc with DirectPage, Globals lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_purge ;sorry there is no segment phx jsr setup_seg_ptrs ;we are now in business lda 1,s ;get the seg number jsr mark_purged @skip_it plx dex ;back off by one and try again cpx #$0001 bne @search_loop @end_purge ; ; unlock all load segments ; lda |USERID ;push the User ID pha _HUnlockAll ; ; purge all other dynamic segments ; lda |USERID ;push the User ID pha _PurgeAll ; ; make all static segments purgeable ; pea $0003 ;Purge Level lda |USERID ;push the User ID pha _SetPurgeAll clc rts mark_purged sta search_seg ;segment we need to nuke jsr make_HET_ptr lda search_seg jsr setup_seg_ptrs ;point to the entry please ldy #HET_Entry.SegFlags ;see of it is loaded lda [HET_entry_ptr],y bmi @do_it @no_seg lda #seg_not_found ;seg_not_found sec rts @do_it ldy #HET_Entry.SegHandle ;lets get the handle lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @have_handle txa beq @no_seg @have_handle stx temp_handle sty temp_handle+2 ;handle to the segment ldy #$0004 ;lets unlock this puppy lda [temp_handle],y and #$7FFF sta [temp_handle],y ldy #HET_Entry.SegFlags ;mark this segment as Purgable lda [HET_entry_ptr],y ora #$0001 sta [HET_entry_ptr],y ;segment is now marked purgable jsr reset_jmp_tables ;go and reset the jump tables for this ID clc rts endp TITLE ', ExpressLoad.a - lock_statics' ;==================================================================================================== ;lock_statics: This routine will check and see if all the static segments are loaded. It will ; also lock all the static segments that it finds. If any of the static segments ; have been purged the routine will error out with the carry set ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error all static segments are not loaded ; b = k ; ; ;==================================================================================================== longa on longi on lock_statics proc with DirectPage, Globals stz temp_word ;If zero on exit then there were no static segments jsr make_HET_ptr ;convert ExpressHandle into pointers lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_lock ;sorry there is no segment phx jsr setup_seg_ptrs ;setup pointer to the Header Entry jsr lock_it plx bcs @error_out dex ;back off by one and try again cpx #$0001 bne @search_loop @end_lock lda temp_word ;see if we encountered any static segments beq @error_out clc rts @error_out sec ;sorry there are no static segments or not all ;segments are still in memory rts lock_it ldy #HET_Entry.SegFlags ;first lets see if this is a static segment lda [HET_entry_ptr],y and #stat_type beq @not_static ;its not static so we do not care about the segment sta temp_word ;this is used as a flag to indicate that there are ;static segments that can be locked ldy #HET_Entry.SegHandle ;now lets see if the segment has been purged lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay ora [HET_entry_ptr] ;check for a null handle bne @handle_OK @bad_handle sec rts ;the handle is scewed up @handle_OK stx temp_handle sty temp_handle+2 ldy #$0002 lda [temp_handle] ora [temp_handle],y ;valid handle? beq @bad_handle ;nope ldy #$0004 ;now lets lock the handle please lda [temp_handle],y ora #$8000 ;set the lock bit sta [temp_handle],y pea #$0000 ;set the purge level to zero pei temp_handle+2 pei temp_handle _SetPurge rts ;carry is set based on the call. @not_static clc rts endp TITLE ', ExpressLoad.a - lock_segment' ;==================================================================================================== ;lock_segment: This routine will make segment purgable and locked ; ; ;Input: A = segment_number ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on lock_segment proc with DirectPage, Globals sta search_seg ;segment we need to lock jsr make_HET_ptr lda search_seg ;segment we need to lock jsr setup_seg_ptrs ;point to the entry please ldy #HET_Entry.SegFlags ;see of it is loaded lda [HET_entry_ptr],y lsr a bcs @do_it ;yep the segment is unlocked clc rts @do_it ldy #HET_Entry.SegHandle ;lets get the handle lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @have_handle txa beq @no_seg @have_handle phy phx ;push the handle stx temp_handle sty temp_handle+2 ;handle to the segment ldy #$0002 ;deref the handle to see if it is nill lda [temp_handle] ora [temp_handle],y bne @lock_it ldy #HET_Entry.SegFlags ;mark segment as gone lda #$0000 sta [HET_entry_ptr],y ldy #HET_Entry.SegHandle sta [HET_entry_ptr],y iny iny sta [HET_entry_ptr],y ;zero the handle also jsr clear_handles ;clear local copy of handle _DisposeHandle stz temp_handle stz temp_handle+2 ;Temp Handle is not valid @no_seg lda #seg_not_found sec rts ;indicate segment is gone @lock_it ldy #$0004 ;lets lock this puppy lda [temp_handle],y ora #$8000 sta [temp_handle],y ldy #HET_Entry.SegFlags ;mark this segment as locked lda [HET_entry_ptr],y and #$FFFE ;clear the Unlocked Bit sta [HET_entry_ptr],y ;segment is now marked purgable plx ply clc ;indicate segment is safely locked down rts endp TITLE ', ExpressLoad.a - load_segment' ;==================================================================================================== ;load_segment: This routine will load a segment into memory ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; HET_entry_ptr ;must be setup ; seg_header_ptr - Pointer to SegHeaderEntry ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on load_segment proc with DirectPage, Globals stz reloc_handle stz reloc_handle+2 ldy #SegHeaderEntry.RelocDict_Hndl ;set handle to zero lda #$0000 sta [seg_header_ptr],y iny iny sta [seg_header_ptr],y jsr conv_attributes ;convert the attributes to something useful ; ;On exit conv_attributes sets A to memory manager Attributes ; sta mem_attr ldy #SegHeaderEntry.LConst_Mark+2 lda [seg_header_ptr] tax lda [seg_header_ptr],y tay lda #absolute jsr set_mark bcc @mark1_set @oops rts ;return the error @mark1_set ldy #SegHeaderEntry.LConst_Length ;now lets get the size of the segment lda [seg_header_ptr],y sta |PRead.requestCount sta LConst_Size iny iny lda [seg_header_ptr],y ;get the high count sta |PRead.requestCount+2 sta LConst_Size+2 ; ;Now lets see if we already have memory. We will have memory if we are reloading a restart segment ; ldy #HET_Entry.SegHandle ;see if we already have the memory segment lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @skip_alloc ;we already have the memory txa bne @skip_alloc ;this must be a restart call lda seg_kind ;what kind of segment is it? bit #kind_abs_bank ;absolute bank segment? bne @just_allocate ;yes, use attributes as is and #kind_only cmp #dp_seg_type ;is it a DP segment? beq @just_allocate ;yes, so we HAVE to allow special memory lda mem_attr ;get the original attributes pha ;save 'em ora #attr_no_spec ;set the 'no-special-memory' bit sta mem_attr @try_again ldx |PRead.requestCount ldy |PRead.requestCount+2 ;load the number of bytes to allocate for the segment jsr alloc_LConst_seg ;allocate the memory for the segment bcs @had_error pla ;restore original attributes sta mem_attr bra @skip_alloc ;all is fine, continue @had_error plx ;retrieve original attributes tay ;save error code lda mem_attr ;get the attributes we just used and #$0008 ;did we allow special memory? beq @oops2 ;yes, and still had a problem! txa ;get the original attributes and #$0008 ;did they allow special memory? bne @oops2 ;no, don't override their wishes stx mem_attr ;restore original attributes phx ;back on stack bra @try_again ;go back and try to allocate again @oops2 tya ;restore error code bra @oops ;and exit @just_allocate ldx |PRead.requestCount ldy |PRead.requestCount+2 ;load the number of bytes to allocate for the segment jsr alloc_LConst_seg ;allocate the memory for the segment bcs @oops @skip_alloc stx temp_handle stx seg_handle sty temp_handle+2 sty seg_handle+2 ldy #HET_Entry.SegHandle ;update the handle address in HET entry txa sta [HET_entry_ptr],y lda temp_handle+2 iny iny sta [HET_entry_ptr],y ldy #$0002 ;deref the handle please lda [temp_handle] sta base_ptr ;address of the image tax lda [temp_handle],y sta base_ptr+2 tay jsr read_wBuf_ptr ;read in the segment please bcc @add_seg_offset rts @add_seg_offset jsr add_segment_offset ;add seg offset to base_ptr return value in X&Y entry load_reloc_dict load_reloc_dict ;go ahead and load the relocation dictionary ; ;Now lets do the relocation dictionary ; ldy #SegHeaderEntry.RelocDict_Mark lda [seg_header_ptr],y tax iny iny lda [seg_header_ptr],y tay bne @data_avail txa beq @its_loaded @data_avail lda #absolute jsr set_mark bcc @mark2_set rts ;return the error @mark2_set ldy #SegHeaderEntry.RelocDict_Length ;now lets get the size of the segment clc lda [seg_header_ptr],y adc #$0001 sta |PRead.requestCount tax iny iny lda [seg_header_ptr],y ;get the high count adc #$0000 sta |PRead.requestCount+2 tay lda |PRead.requestCount ;check for a zero length relocation dictionary dec a ora |PRead.requestCount+2 beq @its_loaded jsr alloc_mem ;allocate the memory for the segment stx temp_handle stx reloc_handle sty temp_handle+2 sty reloc_handle+2 ldy #SegHeaderEntry.RelocDict_Hndl ;save handle to relocation dictionary lda temp_handle sta [seg_header_ptr],y iny iny lda temp_handle+2 sta [seg_header_ptr],y ldy #$0002 ;deref the handle please lda [temp_handle] tax lda [temp_handle],y tay jsr read_wBuf_ptr ;read in the segment please bcc @its_loaded rts @its_loaded ldy #HET_Entry.SegFlags lda [HET_entry_ptr],y ora #$8000 ;mark segment loaded sta [HET_entry_ptr],y lda seg_kind and #kind_only ;lets see if this is a jump table segment cmp #jmp_tbl_seg bne @not_jump jsr patch_jmp_tbl ;we need to setup the jump table entries ldy #HET_Entry.SegFlags ;mark segment as a Jump Segment lda [HET_entry_ptr],y ora #jmp_type sta [HET_entry_ptr],y @not_jump lda seg_kind ;see if the segment is dynamic or static bmi @its_dynamic ldy #HET_Entry.SegFlags ;set the static bit please lda [HET_entry_ptr],y ora #stat_type sta [HET_entry_ptr],y @its_dynamic clc rts entry patch_jmp_tbl patch_jmp_tbl clc lda base_ptr ;please point to the first segment entry adc #seg_jmp_start sta temp_ptr lda base_ptr+2 adc #$0000 sta temp_ptr+2 ;point to the first entry @loop ldy #JE_FileNum ;see if we are done lda [temp_ptr],y beq @done lda |USERID ;save the ID please sta [temp_ptr] ldy #JE_jsl ;index to the JSL instruction lda jump_load_instr ;store the Jump Load Instruction sta [temp_ptr],y iny iny lda jump_load_instr+2 sta [temp_ptr],y @next_entry clc lda temp_ptr adc #jmp_entry_size ;size of one entry sta temp_ptr bcc @loop inc temp_ptr+2 bra @loop @done rts Entry add_segment_offset add_segment_offset ldy #SegHeaderEntry.Entry ;See if this segment is the main segment lda [seg_header_ptr],y tax iny iny lda [seg_header_ptr],y ;get the high word tay bne @seg_offset_true ;we must override the first segment txa bne @seg_offset_true ldx #$0000 txy @seg_offset_true clc txa ;get the low word of the offset adc base_ptr sta segment_entry tya ;get the high word of the segment offset adc base_ptr+2 sta segment_entry+2 rts endp TITLE ', ExpressLoad.a - find_Seg_name' ;==================================================================================================== ;find_seg_name: This routine will locate a segment by name ; ; ;Input: A = undefined ; X = low word pointer to name ; Y = high word pointer to the name ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ;must be setup ; ;Output: A = segment number if found ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = segment not found ; b = k ; ; ;==================================================================================================== longa on longi on find_seg_name proc with DirectPage, Globals stx path_ptr sty path_ptr+2 ;segment name pointer jsr make_HET_ptr ;setup pointer to the Header Entry Table lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @not_found ;sorry there is no segment by this name phx jsr setup_seg_ptrs ;we are now in business jsr compare_names ;see if this is the one bcc @found_it ;we have located the correct segment plx dex ;back off by one and try again cpx #$0001 bne @search_loop @not_found sec rts ;segment is not in ExpressLoad header @found_it pla ;return the segment number clc rts ;return to the caller with the good news compare_names clc ldy #SegHeaderEntry.DispName ;get the displacement lda [seg_header_ptr],y adc #SegHeaderEntry.name_overhead clc adc seg_header_ptr sta temp_ptr lda #$0000 adc seg_header_ptr+2 sta temp_ptr+2 ;temp_ptr now points to the segment name (PString) ldy #SegHeaderEntry.LabLen ;offset to label length field in header lda [seg_header_ptr],y ;get the value and #$00ff ;it's only a byte wide beq @is_length ;length is first byte of string (Pascal style) ldy temp_ptr ;else decrement the string pointer bne @only_low dec temp_ptr+2 @only_low dec temp_ptr sep #$20 ;8-bit store here sta [temp_ptr] ;store the string length (from lablen) rep #$20 @is_length longa off longi off sep #$30 lda [path_ptr] ;get the length of the input name tay cmp [temp_ptr] bne @not_it ;the length is not the same @compare_loop if 0 then ;segment name comparison should be case SENSITIVE lda [temp_ptr],y ;get the character cmp #'a' bcc @no_convert cmp #'z'+1 bcs @no_convert and #$DF ;convert to upper case @no_convert cmp [path_ptr],y ;see if the characters are the same beq @check_next sta temp_word ;save for compare lda [path_ptr],y ;get char from callers area cmp #'a' bcc @not_it ;it cannot be the one cmp #'z'+1 bcs @not_it and #$DF ;convert to upper case cmp temp_word bne @not_it ;sorry wrong name else lda [temp_ptr],y ;get the character cmp [path_ptr],y ;same as supplied? bne @not_it ;nope! endif @check_next dey bne @compare_loop ;keep looking rep #$30 clc rts ;We have found the segment! @not_it rep #$30 sec rts endp TITLE ', ExpressLoad.a - save_dp_info' ;==================================================================================================== ;save_dp_info: This routine will save the direct page address ; ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on save_dp_info proc with DirectPage, Globals lda segment_entry ;address of the stack direct page sta stack_addr lda LConst_Size ;save the size please sta stack_size rts endp TITLE ', ExpressLoad.a - load_statics' ;==================================================================================================== ;load_statics: This routine will load all static segments ; ; ;Input: A = undefined ; 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 load_statics proc with DirectPage, Globals tsx ;save the stack pointer stx stack stz starting_addr stz starting_addr+2 stz stack_addr ;there is no stack stz stack_size static_loop lda #any_kind ;lets find all static segments that are left ldx #static_only ;don't look at other bits ldy #unloaded_state ;skip loaded segments jsr find_Segment ;do the search bcc @another_seg clc @oops rts ;return with no error @another_seg jsr load_segment ;load the segment into memory bcs @oops ldy #SegHeaderEntry.Kind ;lets see if this is a Stack/Direct Page segment lda [seg_header_ptr],y ;If it is then save the correct Info. and #kind_only cmp #dp_seg_type ;lets find the stack seg please bne @not_stack jsr save_dp_info ;save stack and Direct page info bra not_first ;even if it is skip it please @not_stack cmp #init_seg_type ;is this an initilization segment? beq run_init_seg ;go ahead and run the segment lda starting_addr ora starting_addr+2 bne not_first ;this is not the first segment ; ;If this is the first segment then save it's starting address so we can return it to the caller ; lda segment_entry sta starting_addr ;save the starting address that we will jump to lda segment_entry+2 sta starting_addr+2 not_first lda loaded_seg_num ;save the seg number pha jsr static_loop bcs fix_stack_abort ;exit if an error occurred pla jsr Process_Reloc bcs fix_stack_abort ;mjor problems rts run_init_seg lda loaded_seg_num ;the init segment we just loaded! jsr Process_Reloc bcs fix_stack_abort ;exit with the error jsr lock_handles lda segment_entry ;address of the segment just loaded ldy segment_entry+2 jsr Do_Init_Segment jsr unlock_handles bra static_loop ;load any other init segs please fix_stack_abort ldx stack txs ;restore the stack pointer please rts ;return the error to the caller endp TITLE ', ExpressLoad.a - save_start' ;==================================================================================================== ;save_start: This routine will save the starting address and stack info in the user_id_table ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; user_id_ptr ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on save_start proc with DirectPage, Globals ldy #ID_Table_Entry.Stack_Addr ;save the address of the stack/direct page lda stack_addr sta [user_id_ptr],y ldy #ID_Table_Entry.Stack_Size ;also save the size lda stack_size sta [user_id_ptr],y ldy #ID_Table_Entry.Start_Addr lda starting_addr ;save the starting address of the application sta [user_id_ptr],y iny iny lda starting_addr+2 sta [user_id_ptr],y clc rts entry restore_start restore_start ldy #ID_Table_Entry.Stack_Addr ;get the address of the stack/direct page lda [user_id_ptr],y sta stack_addr ldy #ID_Table_Entry.Stack_Size ;get save the size lda [user_id_ptr],y sta stack_size ldy #ID_Table_Entry.Start_Addr lda [user_id_ptr],y sta starting_addr iny iny lda [user_id_ptr],y sta starting_addr+2 clc rts endp TITLE ', ExpressLoad.a - reload_restart' ;==================================================================================================== ;reload_restart: This routine will scan the ExpressLoad segment looking for a restart segment ; If any are found they will be loaded into the same address as they were before. ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on reload_restart proc with DirectPage, Globals jsr make_HET_ptr lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_restarts ;sorry there is no segment phx sta loaded_seg_num jsr setup_seg_ptrs ;we are now in business jsr do_restarts @skip_it plx bcs @restart_error dex ;back off by one and try again cpx #$0001 bne @search_loop @end_restarts clc @restart_error rts do_restarts ldy #SegHeaderEntry.Kind lda [seg_header_ptr],y ;get the segment kind field to determine if this and #Reload_Segment ;segment needs to be reloaded. beq @not_reload jsr load_restart ;major pain in the butt! @not_reload clc rts load_restart lda file_open ;is the file already open? bne @skip_open ;someone has already opened the file jsr open_load_file ;open the file please bcs @load_exit @skip_open jsr load_segment ;load the segment into memory bcs @load_exit ;bad news lda loaded_seg_num ;now relocate the segment jsr Process_Reloc ;process the segment @load_exit rts endp TITLE ', ExpressLoad.a - reload_inits' ;==================================================================================================== ;reload_inits: This routine will scan the ExpressLoad segment looking for init segments. If it finds ; an init segment it will pass control to that segment ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ExpressHandle ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000..1 = error ; b = k ; ; ;==================================================================================================== longa on longi on reload_inits proc with DirectPage, Globals jsr make_HET_ptr lda [HET_ptr] ;get the number of entries in table inc a ;start from the last segment inc a tax @search_loop txa ;pass in the segment number beq @end_inits ;sorry there is no segment phx sta loaded_seg_num jsr setup_seg_ptrs ;we are now in business jsr do_inits @skip_it plx bcs @init_error dex ;back off by one and try again cpx #$0001 bne @search_loop @end_inits clc @init_error rts do_inits ldy #SegHeaderEntry.Kind lda [seg_header_ptr],y ;get the segment kind field to determine if this and #kind_only cmp #init_seg_type beq @do_init_type clc rts @do_init_type ldy #HET_Entry.SegHandle ;get the handle to the segment lda [HET_entry_ptr],y tax iny iny lda [HET_entry_ptr],y tay bne @have_handle tax bne @have_handle sec rts ;return the handle @have_handle stx temp_handle sty temp_handle+2 ldy #$0001 lda [temp_handle] sta self_mod+1 lda [temp_handle],y sta self_mod+2 jsr lock_handles tdc ;save my direct page pha lda #$0000 tcd ;set direct register to real zero page self_mod jsl >$000000 rep #$30 ;restore 16 bit mode pla ;restore direct register tcd phk plb jsr unlock_handles clc rts endp TITLE ', ExpressLoad.a - zero_handles' ;==================================================================================================== ;zero_handles: Zero handles to indicate that there is no segment ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = ? ; ; ;Output: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ; ;==================================================================================================== longa on longi on zero_handles proc with DirectPage ; ;We now zero the handles that do not live across calls. We do this so we can ;lock the handles when we make memory manager calls ; stz ExpressHandle ;zero the handles please stz ExpressHandle+2 stz temp_handle ;zero any temp handles hanging around stz temp_handle+2 stz reloc_handle ;this handle does not live across calls stz reloc_handle+2 stz seg_handle stz seg_handle+2 ;this handles do not live across calls stz curr_id_handle stz curr_id_handle+2 rts endp TITLE ', ExpressLoad.a - rename_segments' ;==================================================================================================== ;rename_segments: This routine will rename paths for ExpressLoad ; ;Input: A = undefined ; X = undefined ; Y = undefined ; P = nvmxdizc ; ..000... ; b = k ; ;Output: A = User ID ; X = undefined ; Y =undefined ; P = nvmxdizc ; ..000..1 = not found ; b = k ; ; ;==================================================================================================== longa on longi on rename_segments proc with DirectPage, Globals newAddr EQU input_parms oldAddr EQU newAddr+4 ldx user_id_handle ldy user_id_handle+2 @keep_going stx temp_handle sty temp_handle+2 ldy #$0002 lda [temp_handle] sta user_id_ptr ;point to the next user_id table lda [temp_handle],y sta user_id_ptr+2 ldy #$0004 ;lock the handle lda [temp_handle],y ora #$8000 sta [temp_handle],y jsr do_rename ;rename all files in this user_id chunk ldy #$0004 ;unlock the handle lda [temp_handle],y and #$7FFF sta [temp_handle],y ldy #User_ID_Table.Next+2 ;get the next link lda [user_id_ptr] tax lda [user_id_ptr],y tay bne @keep_going txa bne @keep_going rts ;we are done do_rename ldy #id_entry_size ;start at the first available spot ldx #id_entry_cnt ;number of entries in a table @rename_loop lda [user_id_ptr],y ;get a user_id beq @empty_slot phy phx jsr check_and_rename ;rename if needed plx ply @empty_slot clc tya adc #id_entry_size tay dex bpl @rename_loop clc rts ;==================================================================================================== ;Rename the segment if needed ;==================================================================================================== check_and_rename Import MemMove iny iny ;get the ExpressHandle lda [user_id_ptr],y tax iny iny lda [user_id_ptr],y tay jsr merge_path ;build a complete pathname jsr compare_paths ;is this the one? bcs @no_match ;yup php ;save partial/full match status lda ExpressHandle ;copy ExpressHandle into generic variable sta Handle lda ExpressHandle+2 sta Handle+2 lda [newAddr] ;get the length of the new name sec sbc [oldAddr] ;calculate difference (may be negative) beq @no_size_change ;if same length, no adjustment necessary jsr adjust_handle_size ;change the size of the Express Segment buffer bcs @no_match ;just punt if we get an error ldy #2 ;deref Handle lda [Handle] sta TempZero lda [Handle],y sta TempZero+2 ldy #ExpressloadSeg.PathnameOffset clc lda [TempZero],y adc TempZero ;offset to position of pathname within segment sta PathnamePtr lda TempZero+2 adc #0 sta PathnamePtr+2 @no_size_change plp ;retrieve complete/partial match status jsr change_pathname ;go make the change @no_match rts ;else we're done with this one entry change_pathname change_pathname php ;save overflow flag bvs @full_match ;complete match, go move the new name in @partial_match lda [oldAddr] ;get length of matching portion of name inc a ;adjust for leading length word inc a clc adc PathnamePtr ;calculate address of remainder of name tax lda PathnamePtr+2 adc #0 pha ;put source pointer on stack phx lda [newAddr] ;get length of new name inc a ;adjust for leading length word inc a clc adc PathnamePtr ;calculate address of destination tax lda PathnamePtr+2 adc #0 pha ;put destination pointer on stack phx lda [PathnamePtr] ;get length of Express segment name sec sbc [oldAddr] ;calculate length of remainder of name pha jsr MemMove ;move the unchanging portion of name in @full_match lda [PathnamePtr] ;get length of original name pha ;save on stack for a bit pei newAddr+2 ;source pointer pei newAddr pei PathnamePtr+2 ;destination address pei PathnamePtr lda [newAddr] inc a ;adjust for leading length word inc a pha jsr MemMove ;move the new name in pla ;retrieve original length plp ;complete or partial match? bvs @done ;complete, so we're done sta [PathnamePtr] ;save here for a bit lda [newAddr] ;calculate difference in size sec sbc [oldAddr] clc ;calculate new length adc [PathnamePtr] sta [PathnamePtr] ;set new length @done rts ;we're done with this name ;==================================================================================================== ; ;This routine will resize the ExpressLoad handle as needed ; ;==================================================================================================== entry adjust_handle_size adjust_handle_size pha ;save the amount of change lda #$0000 pha pha pei Handle+2 ;push the high word of the handle pei Handle _GetHandleSize ldx #0 ;init high word of difference lda 5,s ;get difference value bpl @enlarge ;if positive, must grow the segment dex ;else sign extend the high word @enlarge clc adc 1,s ;calculate the new size tay ;save here for a second txa ;do high word adc 3,s sta 5,s ;save the value back on the stack pla ;remove old size pla phy ;and put low word of new size on stack pei Handle+2 pei Handle _HUnlock ;unlock the handle ; new size is already on stack pei Handle+2 pei Handle _SetHandleSize ;SetHandle size for ExpressLoad segment rts endp