;========================================================== ; Search for Strings routine ; by Andreas Finne ; date: 4 Jul 2000 ; ; Size: 120 bytes ; ; Input: ; DE = word to search for (two bytes) ; HL = place were the table should be placed (Must be on RAM page 0) ; ; Output: ; - NumStrings = number of strings ; - A table containing ABS pointers to the start of data of every ; string. The addresses are stored in AHL format. To use the ; table, load A with the first value, H with the second ; and L with the third. ;========================================================== Search: ld (Label),hl ;Uses selfmodifying code. This basically results in 'ld ix,hl' ld a,d ;Load a with the first ID-byte ld (FirstByte),a ;Change the cp 0 to cp ID-byte ld a,e ;Same thing with second ID-byte ld (SecondByte),a xor a ld (NumStrings),a ;No strings yet ld ix,$0000 ;Point ix to a place were the addresses of the strings are going to be stored Label = $-2 ;This points to the $0000 in the previous line call _ram_page_7 ;This will load RAM page #7 in the area between $8000 and $BFFF ;RAM page 7 contains the VAT (variable allocation table, or something like that) ;Here are the addresses of all the variables on the calc stored. ;It's written backwards so the first entry is at $BFFF. ld hl,$BFFF ;We want to start searching at the beginning (top/bottom) of the VAT. ld bc,($D298) ;$D298 contains the address to the end (bottom/top) of the VAT. inc bc SearchMainLoop: and a ;Clear the carry flag sbc hl,bc ;Subtract the bottom from the top to check if we are done. jr c,DoneSearching ;If carry, we are done searching. push bc add hl,bc ;Add bc to hl so we have the same value as before in hl SearchLoopA: ld a,(hl) ;Load the ID byte for the first entry in the VAT. cp $0C ;We are looking for strings. $0C is the ID byte for strings. jr z,Found ;We found a string. SkipName: dec hl ;Skip ID byte. dec hl ;Skip ABS address dec hl ; dec hl ; dec hl ;Skip an unused byte (This is where shells store the folder number!) ld b,(hl) ;Load b with the length of the name. inc b SkipNameLoop: dec hl ;Skip the name. djnz SkipNameLoop ;After this hl points to the next ID byte. pop bc ;Get the end of the VAT back jr SearchMainLoop ;Goto beginning (almost). Found: ;When we've come this far we have found a string. Now we're going to check ;if it's one of our strings. push hl ;First we save the values so we can continue to search where we left off. dec hl ;hl points to ID byte, dec it so it points to the LSB of the ABS address. ld e,(hl) ;Load the LSB of the ABS address to e dec hl ;hl now points to the middle byte in the address ld d,(hl) ;Load it into d dec hl ;hl points to MSB of the address ld b,(hl) ;Load it into b call _get_size_word ;This puts the size of the string into de and sets the ABS address to start ;of data into AHL ld c,a ;Save a and hl since 'call _getb_ahl' destroys a and hl push hl call _getb_ahl ;ld a,(ahl) Gets byte at ahl into a, and sets the RAM page and ;changes hl to point to the actual place of the string cp 0 ;Is it the first ID-byte? FirstByte = $-1 ;This points to the 0 in the previous line jr z,CheckNext ;If not, continue search LabelSmth: pop hl jr NotOurString CheckNext: inc hl ;Next byte. We can use this since _getb_ahl sets the ram page and pointer ld a,(hl) ;Load the second byte of the string into a cp 0 ;Is it the second ID-byte? SecondByte = $-1 ;This points to the 0 in the previous line jr nz,LabelSmth ; If not - continue search ld a,c ;Restore pop hl ;Yes, we have found one of our strings. Now we save the address to the data call _inc_ptr_ahl ;inc AHL so it points to the first data instead of the second ID-byte ld (ix),a ;Store the address to the string ld (ix+1),h ld (ix+2),l inc ix ;Make ix point to empty space. inc ix inc ix ld a,(NumStrings) ;Update the number of strings inc a ld (NumStrings),a NotOurString: call _ram_page_7 ;Load back RAM page 7 pop hl ;Get current search place back jr SkipName ;Go back to skip the name of the current string DoneSearching: jp _ram_page_1 ;Change back to RAM page 1 NumStrings: .db 0 .end