TITLE ', STRUCT.a - Add_Link' * **************************************************************** * * Add entry to Linked List * * Each entry in a Linked List starts with two 4 byte Handles. * The first is a handle to the next entry * and the second is a handle to the previous entry. * * Inputs: Address of Linked List (TOS+7) * Handle to New Entry (TOS+3) * Outputs: none * **************************************************************** * Add_Link PROC with DirectPage First_Entry equ 7 New_Entry equ 3 ; ; check whether this is 1st entry in Linked List ; ldy #0 lda (First_Entry,s),y ldy #2 ora (First_Entry,s),y bne cont ; ; this is first entry, store handle of new entry in input ; address of Linked List (address assumed to be in same bank ; as this code) ; lda New_Entry+2,s sta (First_Entry,s),y ;Y is still == 2 lda New_Entry,s ldy #0 sta (First_Entry,s),y bra done ;done ; ; this is not first entry, replace address of Linked List with ; Handle to First Entry ; cont lda (First_Entry,s),y ;Y == 2 here sta First_Entry+2,s ldy #0 lda (First_Entry,s),y sta First_Entry,s ; ; Find last entry in linked list ; ; Starting from First Entry, move from Entry to Entry until ; a Entry is found whose Next Entry Handle is NIL. Put the ; Handle to each Entry back on the stack replacing the one ; before. ; loop lda First_Entry+2,s ;Handle of First Entry tay lda First_Entry,s jsr DeRef ;dereference Handle phy ;Pointer on stack pha jsr DeRef ;get Next Entry Handle from First Entry phy ;save on stack pha ora 3,s ;is Next Entry Handle NIL? beq last ;yes, found last Entry lda 1,s ;replace Handle to First Entry with sta First_Entry+8,s ; Next Entry Handle in First Entry tya sta First_Entry+10,s pla ;clean up stack pla pla pla bra loop ;repeat logic ; ; Last Entry in linked list has been found. Handle to First Entry ; on stack is now Handle to Last Entry. Pointer to Last Entry is ; on TOS+5. ; last pla ;remove NIL Handle pla pla ;pull Pointer to Last Entry ply phb ;save DBR jsr UsePtr ;make Pointer usable lda New_Entry+3,s ;store Handle to New Entry tay sta |2,x ; as Next Entry Handle of Last Entry lda New_Entry+1,s sta |0,x plb ;restore DBR jsr DeRef ;dereference handle phb ;save DBR jsr UsePtr ;make Pointer to New Entry usable lda First_Entry+1,s ;store Handle to Last Entry sta |4,x ; in New Entry lda First_Entry+3,s sta |6,x plb ;restore DBR done Stack_Cleanup 8 ;remove parameters rts ;return ENDP TITLE ', STRUCT.a - Remove_Link' * **************************************************************** * * Remove entry in Linked List * * Inputs: Address of Linked List (TOS+7) * Handle of Entry (TOS+3) * * Outputs: none * * Zero Page used: none * * This routine assumes that the Linked List is in Bank 1 * (e.g. in Loader's Global area) * **************************************************************** * Remove_Link PROC with DirectPage Address equ 7+8 Entry equ 3+8 Next equ 5 Previous equ 1 ; ; get Previous handle and Next handle out of Entry ; and put on stack ; lda Entry-6,s ;handle of Entry tay lda Entry-8,s jsr DeRefUse ;dereference Handle and use Pointer lda |2,x ;Next handle pha lda |0,x pha lda |6,x ;Previous handle pha lda |4,x pha ; ; is Entry only one in linked list ? ; (Previous handle = Next handle = 0) ; ora Previous,s tay ;save ora Next,s ora Next+2,s bne cont1 ; ; yes, zero out Address of Linked List ; phk ;restore DBR plb lda #0 ldy #0 sta (Address,s),y ldy #2 sta (Address,s),y bra cont4 ; ; no, is Previous handle of Entry = 0 (i.e. first entry) ? ; cont1 tya bne cont2 ; ; yes, store Next handle of Entry in Address of Linked List ; phk ;restore DBR plb lda Next,s ldy #0 sta (Address,s),y lda Next+2,s ldy #2 sta (Address,s),y bra cont3 ; ; no, point to previous entry ; cont2 lda Previous+2,s tay lda Previous,s jsr DeRefUse ;dereference Handle and use Pointer ; ; set Next handle of previous entry to Next handle of Entry ; lda Next,s sta |0,x lda Next+2,s sta |2,x ; ; is Next handle of Entry = 0 (i.e. last entry) ? ; cont3 lda Next,s ora Next+2,s beq cont4 ; ; no, point to next entry ; lda Next+2,s tay lda Next,s jsr DeRefUse ;dereference Handle and use Pointer ; ; set Previous handle of next entry to Previous handle of Entry ; lda Previous,s sta |4,x lda Previous+2,s sta |6,x ; ; dispose of Entry ; cont4 lda Entry+2,s pha lda Entry+2,s pha _DisposeHandle ; ; remove extra handles from stack ; pla pla pla pla ; ; restore DBR and stack ; phk ;set DBR to PBR plb Stack_Cleanup 8 rts ENDP TITLE ', STRUCT.a - Add_Pathname' * **************************************************************** * * Add new entry in Pathname Table * * Inputs: UserID (TOS+25) * File Number (TOS+23) * Time/Date Stamp (TOS+15) * Direct Page/Stack Addr (TOS+13) * Direct Page/Stack Size (TOS+11) * Starting Address (TOS+7) * Address of Pathname (TOS+3) * * Outputs: New entry linked to last entry (if previous exists) * A - status code * C - set if error * * Zero Page used: Pointer, Handle, TempZero * **************************************************************** * Add_Pathname PROC with DirectPage, Globals IUserID EQU 25 FileNum EQU 23 Date EQU 15 ZP_Addr EQU 13 ZP_Size EQU 11 Address EQU 7 PathName EQU 3 APathTbl equ Pointer lda PathName,s sta TempZero ;store addr of Pathname in zero page lda PathName+2,s sta TempZero+2 ; ; get a memory buffer for new entry ; ldx #0 phx ;space for output Handle phx phx ;BlockSize = lda [TempZero] ; length of File Name clc adc #PT_Path+2 ; +size of constant portion pha pea uPATHTBL ;Owner pea attrNoSpec ;Attributes phx ;Location phx _NewHandle ;get memory buffer plx ply stx Handle ;save returned handle sty Handle+2 bcc @1 jmp error @1 txa jsr DeRef ;dereference handle sta APathTbl ;save address of entry sty APathTbl+2 ; ; zero linked list pointers ; lda #0 ldy #6 @loop sta [APathTbl],y dey dey bpl @loop ; ; set DBR to address of entry ; lda APathTbl ldy APathTbl+2 phb ;save DBR jsr UsePtr ; ; store UserID in new entry ; lda IUserID+1,s sta |PT_UserID,x ; ; store File Number in new entry ; lda FileNum+1,s sta |PT_FileNum,x ; ; if File Number=1, set Jump Table Segment processed flag to 1 ; otherwise, zero it ; cmp #1 beq cont lda #0 cont sta |PT_Jump,x ; ; store File Date and Time in new entry ; lda Date+1,s sta |PT_Date,x lda Date+3,s sta |PT_Date+2,x lda Date+5,s sta |PT_Date+4,x lda Date+7,s sta |PT_Date+6,x ; ; store Zero Page/Stack info in new entry ; lda ZP_Addr+1,s sta |PT_ZP_Addr,x lda ZP_Size+1,s sta |PT_ZP_Size,x ; ; store Starting Address in new entry ; lda Address+1,s sta |PT_Address,x lda Address+3,s sta |PT_Address+2,x ; ; restore DBR ; plb ; ; move File Name into Pathname ; pei TempZero+2 ;source address pei TempZero lda APathTbl ;calculate destination address clc adc #PT_Path tax lda APathTbl+2 adc #^PT_Path pha phx ;destination address pea 0 ;number of bytes lda [TempZero] clc adc #2 pha jsr Block_Move ;call Move function ; ; link new Pathname Table to previous ; pea PATHTBL>>16 pea |PATHTBL pei Handle+2 pei Handle jsr Add_Link ; ; return ; return lda #0 error Stack_Cleanup 24 ;remove input parameters rts ENDP TITLE ', STRUCT.a - Find_Pathname' * **************************************************************** * * Find entry in Pathname Table * * Inputs: UserID (TOS+9) * File Number (TOS+7) * Address of Pathname (TOS+3) * * Outputs: none * X - low bytes of Pointer to entry * DBR - bank * Handle- Handle of entry * A - status code * C - set if error * Counter - if no find, contains max File Number * * Zero Page used: Handle, TempZero, Counter * * This routine will search the Pathname Table for an entry that satisfies * each of the input parameters. If a parameter is 0, it is not used as * a criteria. If no such entry is found, Counter will contain the max * File Number encountered (which is only useful if a UserID is specified) * * Before calling this routine, the User should save the DBR. * * After calling this routine and making all references to the entry, * the User must restore the original DBR. * * This routine can also be used to walk through the Pathname Table * by calling the 'Find_Pathname' entry once and then calling the * 'Next_Pathname' entry for each subsequent entry. The Direct Page variable * 'Handle' will point to the handle of the current entry so it should be * bumped to the handle of the next entry between 'Next_Pathname' calls. * **************************************************************** * Find_Pathname PROC with DirectPage, Globals IUserID EQU 9 FileNum EQU 7 Path EQU 3 lda |PATHTBL sta Handle ;handle to 1st entry lda |PATHTBL+2 sta Handle+2 stz Counter ENTRY Next_Pathname Next_Pathname loop1 lda Handle ;is handle 0? ora Handle+2 bne cont1 lda #NoFind ;yes, No Find error phk ;set DBR to PBR plb jmp error cont1 lda Handle ldy Handle+2 jsr DeRefUse ;dereference Handle and use Pointer ; ; if input UserID­0, compare with value in entry ; lda IUserID,s beq cont2 cmp |PT_UserID,x bne eloop2 ; ; if input File Number­0, compare with value in entry ; cont2 lda FileNum,s beq cont5 cmp |PT_FileNum,x bne eloop2 ; ; if pathname specified, compare with pathname in entry ; cont5 lda Path,s ora Path+2,s beq return ;found match, done lda Path,s sta TempZero lda Path+2,s sta TempZero+2 txa clc adc #PT_Path sta TempZero+4 phb phb pla and #$00FF bcc @1 ;propage carry for possible inc a ;bank crossing @1 sta TempZero+6 lda [TempZero] inc a tay sep #$20 longa off loop2 lda [TempZero],y eor [TempZero+4],y ;case insensitive comparison and #$DF ;ignore the case bit bne eloop2 dey bpl loop2 bra return ;matches eloop2 rep #$20 longa on ; ; set Counter=max(Counter,File Number) ; lda |PT_FileNum,x cmp Counter bcc eloop1 sta Counter ; ; continue to next entry ; eloop1 lda |PT_Next,x sta Handle ;bump Handle to Next Handle lda |PT_Next+2,x sta Handle+2 jmp loop1 ;continue checking ; ; normal return ; return rep #$20 longa on lda #0 ;OK return error Stack_Cleanup 8 ;remove input parameters rts ENDP TITLE ', STRUCT.a - Get_Pathname' * **************************************************************** * * Get Pathname * * Inputs: Handle - Handle to Pathname Table entry * * Outputs: TempBuff - Address of temporary buffer containing pathname * A - status * C - set if error occurred * * Zero Page used: Pointer * * The pathname in the Pathname Table entry is moved into * a temporary buffer. This buffer should be disposed after * the pathname is used. * **************************************************************** * Get_Pathname PROC with DirectPage ; ; lock input handle ; pei Handle+2 pei Handle _HLock ; ; set Pointer to address of pathname using Handle to entry ; lda Handle ldy Handle+2 jsr DeRef clc adc #PT_Path sta Pointer bcc @1 iny @1 sty Pointer+2 ; ; extract length of pathname and save ; lda [Pointer] inc a inc a pha ; ; get a temporary buffer ; jsr Get_TempBuff ; ; unlock input handle ; pei Handle+2 pei Handle _HUnlock ; ; unsave length of pathname ; plx ; ; copy pathname to temporary buffer ; pei Pointer+2 ;Source pei Pointer pei TempBuff+2 ;Destination pei TempBuff pea 0 phx ;Size jsr Block_Move error rts ENDP TITLE ', STRUCT.a - Convert_Pathname' * **************************************************************** * * Convert Pathname * * Inputs: A,Y - Address of Pathname * X - pathname conversion code (0-Type 0 to 1) * (1-Type 1 to 0) * * Outputs: TempBuff - Address of converted pathname * A - status * C - set if error occurred * * Zero Page used: TempZero * * A temporary buffer is allocated for the converted pathname and * should be disposed after the pathname is used. Use the DisposeAll * function with UserID 'uTempBuff' to dispose of the temporary buffer. * **************************************************************** * Convert_Pathname PROC with DirectPage ; ; save inputs in direct page ; sta TempZero sty TempZero+2 stx TempZero+4 ; ; calculated converted pathname size ; lda [TempZero] inc a dex ;if class 0 string, use 1st byte beq cont1 ;if class 1 string, use word and #$00FF inc a ; ; get temporary buffer for full pathname ; cont1 jsr Get_TempBuff pei TempZero+2 pei TempZero pei TempBuff+2 pei TempBuff ; ; check conversion code ; ldx TempZero+4 dex beq cont2 ; ; class 0 to 1 requested, call GS/OS Convert 0 routine ; jsl CVT_0TO1 bcc return bra error ; ; class 1 to 0 requested, call GS/OS Convert 1 to 0 routine ; cont2 jsl CVT_1TO0 bcs error ; ; replace the :'s in the pathname with /'s ; lda [TempZero] tay sep #$30 longa off longi off loop lda [TempBuff],y cmp #':' bne eloop lda #'/' sta [TempBuff],y eloop dey bne loop rep #$30 longa on longi on tya ;zeroize accumulator (no error) rts error lda #BadPath return rts ENDP TITLE ', STRUCT.a - Expand_Pathname' * **************************************************************** * * Expand Pathname * * Inputs: A,Y - Address of Partial Pathname * * Outputs: TempBuff - Address of full pathname * A - status * C - set if error occurred * * Zero Page used: TempZero, Counter * * A temporary buffer is allocated for the full pathname and should be * disposed after the pathname is used. Use the DisposeAll function * with UserID 'uTempBuff' to dispose of the temporary buffer. * **************************************************************** * Expand_Pathname PROC with DirectPage, Globals ; ; save address of partial pathname ; sta TempZero sty TempZero+2 ; ; setup Expand_Path packet ; sta |PExpandPath.inputPath ;input partial pathname sty |PExpandPath.inputPath+2 lda #3 sta |PExpandPath.pCount ;parameter count ; lda #$8000 ; sta |PExpandPath.flags ;uppercase flag stz |PExpandPath.flags ;uppercase flag (no uppercasing) ; ; get length of partial pathname ; lda [TempZero] ; ; calculate initial buffer size = length of partial pathname +4 ; cont2 clc adc #4 sta Counter ; ; get temporary buffer for full pathname ; jsr Get_TempBuff ; ; set length of buffer in output string buffer ; lda Counter sta [TempBuff] ; ; store address of buffer in Expand_Path packet ; lda TempBuff sta |PExpandPath.outputPath lda TempBuff+2 sta |PExpandPath.outputPath+2 ; ; call GS/OS Expand_Path ; jsl $E100A8 dc.w ExpandPath dc.l PExpandPath ; ; if buffer too small, get needed size and try again ; bcc cont5 cmp #buffTooSmall bne cont3 ldy #2 lda [TempBuff],y bra cont2 ; ; if GS/OS is active, that means that GS/OS called RenamePath and we can ; assume that the input filename is already expanded and in correct format ; cont3 cmp #gsosActive beq cont4 sec ;any other GS/OS error is really an error bra error cont4 lda TempZero sta TempBuff lda TempZero+2 sta TempBuff+2 bra return ; ; otherwise, point TempBuff to start of pathname ; cont5 lda TempBuff clc adc #2 sta TempBuff bcc return inc TempBuff+2 return lda #0 clc error rts ENDP TITLE ', STRUCT.a - Add_MemSeg' * **************************************************************** * * Add entry to Memory Segment Table * * Inputs: Memory Handle (TOS+11) * User ID (TOS+9) * Load File Number (TOS+7) * Load Segment Number (TOS+5) * Load Segment Kind (TOS+3) * * Outputs: New table linked to last table (if previous exists) * A - status code * C - set if error * * Zero Page used: TempZero * **************************************************************** * Add_MemSeg PROC with DirectPage, Globals IHandle equ 11 IUserID equ 9 FileNum equ 7 SegNum equ 5 Kind equ 3 ; ; get a memory buffer for new entry ; lda #0 ;space for output Handle pha pha pea MS_Kind+2>>16 ;BlockSize pea |MS_Kind+2 pea uSEGTBL ;Owner pea attrNoCross+attrNoSpec ;Attributes pha ;Location pha _NewHandle ;get memory buffer plx ply stx TempZero ;save returned handle sty TempZero+2 bcs error txa jsr DeRefUse ;dereference Handle and use Pointer ; ; store components into Memory Segment entry ; stz |MS_Next,x stz |MS_Next+2,x stz |MS_Prev,x stz |MS_Prev+2,x lda IUserID,s sta |MS_UserID,x lda IHandle,s sta |MS_Handle,x lda IHandle+2,s sta |MS_Handle+2,x lda FileNum,s sta |MS_FileNum,x lda SegNum,s sta |MS_SegNum,x lda Kind,s sta |MS_Kind,x phk ;restore DBR to PBR plb ; ; link new entry to previous ; pea SEGTBL>>16 pea |SEGTBL pei TempZero+2 pei TempZero jsr Add_Link ; ; return ; lda #0 ;OK return error Stack_Cleanup 12 ;remove input parameters rts ENDP TITLE ', STRUCT.a - Find_MemSeg' * **************************************************************** * * Find entry in Memory Segment Table * * Inputs: User ID (TOS+7) * Load File Number (TOS+5) * Load Segment Number (TOS+3) * * Outputs: Handle of entry (TOS+9) * X - low bytes of Pointer to entry * DBR - bank * Handle - Handle of Next entry * A - status code * C - set if entry not found or error ocurred * * Zero Page used: Handle * * If any of the inputs are 0, no comparison is made for that field. * * Be careful! The DBR will be changed by this routine and the * calling program should restore its original DBR after referencing * the data in the entry. * * This routine can also be used to walk through the Memory Segment Table * by calling the 'Find_MemSeg' entry once and then calling the * 'Next_MemSeg' entry for each subsequent entry. The Direct Page variable * 'Handle' will point to the handle of the next entry so should not be * changed between 'Next_MemSeg' calls. * **************************************************************** * Find_MemSeg PROC with DirectPage, Globals OHandle equ 9 IUserID equ 7 FileNum equ 5 SegNum equ 3 lda >SEGTBL sta Handle ;handle to 1st entry lda >SEGTBL+2 sta Handle+2 ENTRY Next_MemSeg Next_MemSeg loop lda Handle ;is handle NIL? ora Handle+2 bne cont1 lda #NoFind ;yes, No Find error bra error cont1 lda Handle+2 ;handle to entry tay sta OHandle+2,s ;save as output lda Handle sta OHandle,s jsr DeRefUse ;dereference Handle and use Pointer lda |MS_Next,x sta Handle ;bump Handle to Next Handle lda |MS_Next+2,x sta Handle+2 ; ; compare inputs with values in entry ; lda IUserID,s beq cont2 cmp |MS_UserID,x bne loop cont2 lda FileNum,s beq cont3 cmp |MS_FileNum,x bne loop cont3 lda SegNum,s beq return cmp |MS_SegNum,x bne loop ; ; normal return ; return lda #0 ;OK return error Stack_Cleanup 6 ;remove input parameters rts ENDP TITLE ', STRUCT.a - Remove_UserID' * **************************************************************** * * Remove entries from Table * * Inputs: UserID (TOS+7) * Address of Linked List (TOS+3) * * Outputs: none * * Zero Page used: Handle, TempZero * * This routine can be used to remove entries from the * Pathname Table, Jump Table List and any other Table * that: * * 1. is a linked list (with forward and back handles) * 2. first entry is UserID * **************************************************************** * Remove_UserID PROC with DirectPage IUserID equ 7 Address equ 3 lda Address+2,s tay lda Address,s jsr DeRef sta Handle ;handle to 1st entry sty Handle+2 loop ora Handle+2 beq return ;yes, finished lda Handle ;Y still has high word jsr DeRefUse ;dereference Handle and use Pointer ; ; save next Handle ; lda |0,x sta TempZero lda |2,x sta TempZero+2 ; ; check UserID ; lda |8,x phk ;restore DBR plb cmp IUserID,s bne eloop ; ; unlink this entry ; lda Address+2,s ;address of Pathname Table pha lda Address+2,s pha pei Handle+2 ;handle to this entry pei Handle jsr Remove_Link ; ; continue to next entry ; eloop lda TempZero+2 sta Handle+2 ;bump Handle to Next Handle tay lda TempZero sta Handle bra loop ; ; normal return ; return phk ;restore DBR plb Stack_Cleanup 6 ;remove input parameters rts ENDP TITLE ', STRUCT.a - Unload_JTL' * **************************************************************** * * Unload Jump Table Entries * * Inputs: User ID (TOS+7) * Load File Number (TOS+5) * Load Segment Number (TOS+3) * * Outputs: none * * Zero Page used: none * * This subroutine will make all entries with the * specified components in the Jump Table unloaded. * * If Load File Number or Load Segment Number is 0, * no comparison is made for that field * **************************************************************** * Unload_JTL PROC with DirectPage, Globals IUserID equ 7+4 FileNum equ 5+4 SegNum equ 3+4 ; ; push 1st entry in Jump Table List ; lda |JMPTBL+2 pha lda |JMPTBL pha loop1 ora 3,s ;is handle 0? beq return ;yes, we are finished cont1 lda 3,s ;no tay lda 1,s jsr DeRefUse ;dereference Handle and use Pointer ; ; is this Jump Table List entry for specified UserID? ; lda |JT_UserID,x cmp IUserID,s bne eloop1 ;if not, skip this entry ; ; find Jump Table ; lda |JT_Handle,x ldy |JT_Handle+2,x jsr DeRef ;dereference handle bcs eloop1 ;skip if handle is NIL jsr UsePtr ;make pointer useable ; ; move X past 8 zero bytes to first entry in Jump Table ; (this will not be necessary when Linker changed) ; txa clc adc #8 tax ; ; compare inputs with values in entry ; loop2 lda |JE_UserID,x beq eloop1 ;if UserID=0, no more entries cmp IUserID,s ;redundant check for UserID bne eloop2 cont2 lda FileNum,s beq cont3 cmp |JE_FileNum,x bne eloop2 cont3 lda SegNum,s beq cont4 cmp |JE_SegNum,x bne eloop2 ; ; entry satisfies input conditions, make unloaded ; cont4 lda >jump_load_instr ;JSL instruction and 1st byte of address sta |JE_jsl,x lda >jump_load_instr+2 ;last two bytes of address sta |JE_jsl+2,x ; ; bump X to next entry ; eloop2 txa clc adc #JE_jsl+4 tax bra loop2 ; ; bump Handle to next Jump Table List entry ; eloop1 lda 3,s tay lda 1,s jsr DeRefUse ;dereference Handle and use Pointer lda |JT_Next+2,x sta 3,s lda |JT_Next,x ;bump Handle to Next Handle sta 1,s bra loop1 return pla ;pull last Handle off stack pla Stack_Cleanup 6 ;remove input parameters phk ;set DBR to PBR plb rts ENDP TITLE ', STRUCT.a - Cleanup' * **************************************************************** * * Cleanup Routine * * Inputs: UserID (2 bytes) (TOS+3) * * Outputs: none * * Zero Page used: TempZero, Handle * **************************************************************** * Cleanup PROC with DirectPage, Globals IUserID equ 3 ; ; if UserID is not 0, remove UserID from Jump Table first ; lda IUserID,s beq cont pha pea JMPTBL>>16 pea |JMPTBL jsr Remove_UserID ; cont lda IUserID,s ;UserID pha ldx #0 ;Load File Number (all) phx phx ;Load Segment Number (all) phx ;Dynamic Only Flag (no) phx ;Purge Level (real purge) jsr Purge_Segment return lda #0 ;OK return error Stack_Cleanup 2 ;remove input parameters rts ENDP