Sitenotice: 11/29/2018: The wiki is back. It turns out, some anti-virus product on my web server had an issue with the latest version of PHP. My server techs have resolved this issue, and things should be working again. During the investigation, I did restore to a backup from September. There is a chance that any changes done since then were lost, but I do not recall any edits. --OS-9 Al

8/30/2016: Massive re-work is being done on the InfoBox Templates. Read that page to keep up with the plan for that, and adding better keyword tags (categories) to all the pages. --OS-9 Al (talk) 15:28, 31 August 2016 (CDT)

Undercolor/850103/Find

From CoCopedia - The Tandy/Radio Shack Color Computer Wiki
Jump to: navigation, search

Home Articles Companies Publications Hardware People Software Timeline ... Emulators Internet Resources
(Don't see something listed? Click "edit" and add it! Together we can build this database. When making a new info page, refer to this InfoBox Template for guidelines.)



UnderColor, Volume 1, Number 3, January 11, 1985

  • Title: Find
  • Author: Stephen Allen
  • Synopsis: A new word in Basic.
  • Page Scans: Link

Article

Remember "System Horizons" (TCCM, July ’84)? "Find" is a follow-up to that article, and it has finally found a home!

To disassemble Basic ROMs; to be an "insider" on the real processes taking place in your computer; these impart fun and satisfaction, but more satisfying is taking Basic’s own subroutines and using them to create your own programs. You’ll get a great deal of power from a very small piece of code.

What does Find do?

Say you’ve been working on a long Basic program and you keep getting ?FC ERROR in a line you know is legal. Suddenly you realize you need to change a single occurrence

of N$(A) to N$(B). You can do nothing but List the program, hitting Shift @ ’til you find it (if you find it; oops! Try again . . .), then Break and Edit the correct line. A drag, right'?

The Find utility lets you type FINDN$(A) and enter. A listing instantly appears and scrolls furiously by, just as in List. When a line containing the target string is listed, however, the display freezes and a gentle blue cursor marks (in this case) N$(A)'s position in the line.

At this point you have three options. You can hit Break and break out of Find, or you can hit Enter and continue the listing and search. Or (and this is the best part), you can

hit E and go immediately to Extended Color Basic’s Edit routine.

Want to search for the same string a second time? Just type FIND and enter. Find has its own 10-character buffer, so that’s your maximum target string length.

How about wild card searches? Sure! The symbol is #. Searching for PR##T will locate PRINT, PRESTO, PR$(T), etc.

If you're searching for a string containing a Basic word, use a single quotation mark before the word. For example: FIND"'PUT. The quotation mark keeps Basic from turning the string into a token, and is good practice generally, since (for example) NONE; without the mark is tokenized into N/ token for ON/E. Find understands the quotation mark and skips it when it’s the first character.

If your Basic program is already in memory and you need to load Find, don’t worry. Find has two parts: the guts, which contain the routine, and the Pretty Smart Loader, used only once, which sets up operation of the routine. Together, they load into low graphics memory. Even if you've executed PCLEAR1 you're OK. Just (C)LOADM and Execute to set it up, and you're in business.

All this power takes only 250 bytes!

Details

Note: from here on, if there’s something you don't understand, please refer back to "Exploring System Horizons"

(TCCM, July ’84).

Here's the sequence of operations for The Pretty Smart Loader:

1. Get the highest RAM address from Basic's Pointer. Subtract the length of the "guts." Give the new value back to Basic.

2. Copy the "guts" up to that high RAM space.

3. Use the existing RAM token tables to compute a new token for Find, then create a new table for Find. POKE the calculated token value into the guts, to be used as a validation check.

4. Since we don't want this loader executed more than once, change the EXEC address to 41175. If you Execute again, you’ll get Color Basic's sign-on message.

5. If you`re running Extended Color Basic, there'll be a conflict between the new token table and the USR address table. Disk Basic also has this problem, but resolves it by

moving the USR table up into Disk RAM. My solution is to move the USR table up two bytes, keeping USR0 and 1, but taking away USR9, whose address becomes part of the keyboard roll-over table! (When is the last you saw DEFUSR9?) It’s the best trade-off I could think of.

The Guts: Find is always entered with its token in the A register. A quick check is done to see if Basic got there by mistake. If everything's OK (always is), then proceed.

1. Evaluate and store the target string. This is the string which Find will try to match. If no string is specified, use the

last string.

2. Use a ROM call to de—tokenize the next line into a buffer at $2DD.

3. Print a character from the buffer, testing for a match. If there is no match, keep printing and checking.

4. If the character matches, suspend printing and compare the rest of the target string. If the rest of the match fails, resume printing. If the match is successful, set a flag and

pay attention to the match’s position in the line (Line 2100, CLRB). Resume printing and checking.

5. At the end of the line test the flag. If there is no match, do another line.

6. There's a match. Get the screen position of the end of the line, move back to the point of the match, and set a cursor there. Wait for a key press. The instruction INCB in Line 2300 adjusts for the fact that the cursor points one byte ahead of the last printed character.

7. Key Press: If the key was Enter, do another line. If Break, exit Find and jump to Basic’s Break routine. If E, then exit

Find and jump to Edit in ROM. If none of the above, go back and wait. (end)

Listings

00100 *************************
00110 **                     **
00120 ** FIND                **
00130 *************************
00140 ** A New Word For      **
00150 **      Basic          **
00160 *************************
00170 * by                    *
00180 * Stephen P. Allen      *
00190
00200
00210
00220
00230 * For Disk Basic use this ORG
0F00 00240 ORG $F00
00250
00260 * For Extended Basic use this ORG
00270 * ORG $700
00280
00290 *************************
00300 * THE                   *
00310 * PRETTY SMART          *
00320 * LOADER                *
00330 *************************
00340
00350
00360
00370 *** MAKE ROOM UP TOP ***
00380
00F9 00390 LENGTH EQU ZEND-TITLE
00400
0F00 DC 74 00410 START LDD <$74 High Ram address
0F02 83 00F9 00420 SUBD #LENGTH —Find's length
0F05 DD 74 00430 STD <$74 =New "High Ram" address
0F07 DD 27 00440 STD <$27 and "Top of String Space"
0F09 DD 23 00450 STD <$23 and pointer to next string
00460
0F0B 83 00C8 00470 SUBD #200 default total string space
0F0E DD 21 00480 STD <$21 to "Start of String Space"
0F10 10DE 21 00490 LDS <$21 Stack goes below strings
00500
00510 *** MOVE IT UP ***
00520
0F13 DE 74 00530 LDU <$74 New "Top of Ram"
0F15 33 42 00540 LEAU 2,U (a little space, just in case)
0F17 30 8C 41 00550 LEAX <TITLE,PCR Start of "FIND"
0F1A 108E 00F9 00560 LDY #LENGTH of "FIND"
0F1E A6 80 00570 PUTHI LDA ,X+
0F20 A7 C0 00580 STA ,U+
0F22 31 3F 00590 LEAY -1,Y
0F24 26 F8 00600 BNE PUTHI
00610
00620
00630 *** TELL BASIC WHERE TO FIND IT ***
00640
0F26 CE 0116 00650 LDU #$116 Address of (token tables-10)
0F29 5F 00660 CLRB Token will form here
00670
00680
0F2A 33 4A 00690 TABLE LEAU 10,U Move into next Token Table
0F2C EB C4 00700 ADDB ,U add # of entries this table
0F2E 6D C4 00710 TST ,U At end of tables yet?
0F30 26 F8 00720 BNE TABLE no, keep going
00730
0F32 CB 80 00740 ADDB #$80 Make negative, signal as token
0F34 6F 4A 00750 CLR 10,U Signal new "End of Tables"
0F36 86 01 00760 LDA #1 One new entry here
0F38 A7 C0 00770 STA ,U+ At start this new table
00780
00790 * Recalculate start of "FIND"
00800
0F3A 9E 74 00810 LDX <$74 High Ram address
0F3C 30 02 00820 LEAX 2,X plus that two (just in case)
0F3E AF C1 00830 STX ,U++ Address of word into Table
00840
0F40 30 04 00850 LEAX 4,X Address of routine...
0F42 AF C4 00860 STX ,U into the table
00870
00880 * New token also goes directly into routine *
00890
0F44 E7 01 00900 STB 1,X
00910
00920 *Change EXEC address to disable Loader
00930
0F46 8E A0D7 00940 LDX #41175 Color Basic's Sign-on msg.
0F49 9F 9D 00950 STX <$9D to EXEC pointer
00960
00970
00980 *Move DEFUSR table if necessary*
00990
0F4B DC B0 01000 LDD <$B0 Points to DEFUSR table
0F4D 1083 013E 01010 CMPD #$13E Extended Basic's table?
0F51 26 04 01020 BNE JUMP if not, then Disk: OK
0F53 C6 40 01030 LDB #$40 Else Make new table at $140
0F55 DD B0 01040 STD <$B0
01050
0F57 6E 9F FFFE 01060 JUMP JMP [$FFFE] Done! Go do a warm start.
01070
01080
01090 ************************
01100 * THE GUTS *
01100 *************************
01120
01130 * "FIND" with "D" made negative
01140
0F5B 46 01150 TITLE FCC /FIN/
49
4E
0F5E C4 01160 FCB $80+'D
01170
01180
01190 * Routine starts here *
01200
0F5F 81 CE     01210 FIND   CMPA  #$CE   If disk, this will change
0F61 27 03     01220        BEQ   OK     yes, correct token
0F63 7E B277   01230        JMP   $B277  else ?SN ERROR
01240
01250
01260 *** GET THE PARAMETERS ***
01270
0F66 9D 9F     01280 OK     JSR   <$9F   next character
0F68 27 1C     01290        BEQ   FIND2  if null, use previous string
01300
01310 * A string is specified
01320
0F6A 30 8D 00DC 01330       LEAX  TARGET,PCR Point to buffer
0F6E 5F        01340        CLRB       Length of string so far, 0
0F6F 81 22     01350        CHPA   #'"  String delimiter?
0F7l 26 04     01360        BNE    LOOP1
OF73 9D 9F     01370        JSR    <$9F   if so, skip it
OF75 27 0F     01380        BEQ    FIND2  if nothing else specified
01390
0F77 A7 80     01400 LOOP1  STA    ,X+ character into FIND's buffer
0F79 5C        01410        INCB length=1ength+1
0F7A C1 0A     01420        CMPB   #10    max # of chars?
0F7C 24 04     01430        BHS    DONE   if yes, skip the rest
0F7E 9D 9F     01440        JSR    <$9F   else get next char.
0F80 26 F5     01450        BNE    LOOP1  if another char, loop back
01460
0F82 E7 8D OOC3 01470 DONE  STB    LENTS,PCR Store string length
01480
0F86 32 62     01490 FIND2  LEAS   2,S   Drop return address
0F88 8E 0019   01500        LDX    #$19  Has address of first line
0F8B 9F 66     01510        STX    <$66  Save for LIST loop
01520
01530
01540 *** LIST A LINE: TEST FOR MATCH ***
01550
0F8D BD B95C   01560 NXTLIN  JSR   $B95C  Do a linefeed
0F9O BD A549   01570         JSR   $A549  Test for (Break}, (shift @>
01580
0F93 9E 66     01590         LDX   <$66   get address of last line
0F95 AE 84     01600         LDX   ,X    Point to next line
0F97 EC 84     01610         LDD   ,X     End of Basic program?
0F99 26 03     01620         BNE   CONT  if not end of Basic program
0F9B 7E AC73   01630         JMP   $AC73 Exit here if End of Program
01640
0F9E 9F 66     01650 CONT    STX   <$66 Update Low Ram Line Pointer
0FA0 6F 8D 00A2 01660        CLR   FFLAG,PCR No matches this line yet
01670
0FA4 EC 02     01680          LDD  2,X   Get line number
0FA6 BD BDCC   01690          JSR  $BDCC Print line number
0FA9 BD B9AC   01700          JSR  $B9AC print a space
01710
0FAC 9E 66     01720          LDX  <$66  Point to Basic line again
0FAE BD B7C2   01730          JSR  $B7C2 De-Tokenize into buffer
0FBl CE 02DD   01740          LDU  #$2DD Point to buffer
0FB4 31 8D 0092 01750         LEAY TARGET,PCR Point to Target string
0FB8 A6 C0      01780 PRINT LDA ,U+     Next char. from buffer
0FBA 27 2E      01790       BEQ TEST    if End of Line
0FBC AD 9F A002 01800       JSR [$A002] Print the next character ]
0FC0 5C         01810       INCB        Keep track of match position
0FC1 A1 A4      01820       CMPA ,Y     Match on first letter?
0FC3 26 F3      01830       BNE PRINT   if not, keep going
01840
01850 * MATCH ON FIRST LETTER *
01860
0FC5 34 64      01870 MATCH1 PSHS U,Y,B Save important registers
0FC7 33 5F      01880        LEAU -1,U  Prepare for following loop
0FC9 E6 8D 007C 01890        LDB LENTS,PCR Length of Target string
0FCD 5A         01900 MATCH2 DECB       One less Target char to match
0FCE 27 12      01910        BEQ FOUND   If match on total string
0FD0 33 41      01920        LEAU 1,U    Else move up in buffer...
0FD2 31 21      01930        LEAY 1,Y    and Target buffer
0FD4 A6 A4      01940        LDA ,Y      Next target character
0FD6 81 23      01950        CMPA #'#    Is it a "Wildcard?"
0FD8 27 F3      01960        BEQ MATCH2  if yes, automatic match
0FDA A1 C4      01970        CMPA ,U     else test for match
0FDC 27 EF      01980        BEQ MATCH2  so far so good
01990
02000 *Match fails in mid—string
02010
0FDE 35 64      02020        PULS B,Y,U Restore crunched registers
0FE0 20 D6      02030        BRA PRINT   and keep going
02040
02050
02060 *** FOUND A MATCH ***
02070
0FE2 6C 8C 61   02080 FOUND  INC <FFLAG,PCR Flag a match on this line
0FE5 35 64      02090        PULS B,Y,U restore crunched registers
0FE7 5F         02100        CLRB        Print distance from this
02110 *                 match=0
0FE8 20 CE      02120        BRA PRINT   Keep listing to End of Line
02130
02140
02150 * END OF LINE:
02160 * IF THERE'S A MATCH THEN SHOW IT,
02170 * ELSE DO NEXT LINE
02180
0FEA EF 8C 5A   02190 TEST   STU <BUFEND,PCR Save in case of EDIT
0FED 6D 8C 56   02200        TST <FFLAG,PCR Any matches?
0FF0 27 9B      02210        BEQ NXTLIN   if not, do next line
02220
02230
02240 * GOT A MATCH:
02250 * PUT CURSOR AND WAIT FOR KEYPRESS
02260
02270 * First, move cursor to start of last match
02280
0FF2 DE 88      02290 SHOWIT  LDU <$88   Get current cursor position
0FF4 5C         02300         INCB       Adjust for offset
0FF5 33 5F      02310 FINDIT  LEAU -1,U  Move cursor pos. back...
0FF7 5A         02320         DECB
0FF8 26 FB      02330         BNE FINDIT till start of match B
0FFA A6 C4      0234O         LDA ,U Save for non—destructive...
0FFC A7 8C 47   02350         STA <FFLAG,PCR cursor routine
02360
02370 * Now wait for keypress
0FFF 86 AF         02390 CURSOR LDA #$AF blue graphics block...
1001 A7 C4         02400        STA ,U to screen
1003 8D 21         02410        BSR CRSKEY try for keypress
1005 26 09         02420        BNE PRESS if keypress detected
02430
1007 A6 8C 3C      02440        LDA <FFLAG,PCR Else get first letter
100A A7 C4         02450        STA ,U and store on screen
100C 8D 18         02460        BSR CRSKEY and try for keypress
100E 27 EF         02470        BEQ CURSOR Keep trying if nothing
02480
02490
02500 *** GOT A KEYPRESS ***
02510
1010 E6 8C 33      02520 PRESS LDB <FFLAG,PCR Restore first letter...
1013 E7 C4         02530       STB ,U   to screen
02540
1015 81 0D         02550       CMPA #$0D Keypress was <Enter>?
1017 1027 FF72     02560       LBEQ NXTLIN If yes, do next lines
101B 81 45         02570       CMPA #'E 'Keypress was "EDIT?"
101D 27 16         02580       BEQ EDIT if yes
101F 81 03         02590       CMPA #3 Keypress was <Break>?
1021 26 DC         02600       BNE CURSOR if not, keep trying for
02610 *                legal key
02620
1023 7E AE09       02630       JMP $AE09   Exit here on <Break>
02640
02650
1026 108E 028A     02660 CRSKEY LDY #650   Delay value
02670
102A AD 9F A000    02680 DELAY JSR [$A000] Poll keyboard
102E 26 04         02690 BNE KEYEND Exit if keypress
1030 31 3F         02700       LEAY -1,Y else delay a little
1032 26 F6         02710       BNE DELAY
1034 39            02720 KEYEND RTS      Return with or without keypress
02730
02740
02750 *** SET UP EDIT ROUTINE ***
02760
1035 BD B95C       02770 EDIT  JSR $B95C   Do an <Enter>
1038 9E 66         02780       LDX <$66   Point to start of line
103A EC 02         02790       LDD 2,X     grab line number...
103C DD 2B         02800       STD <$2B    and save for printout
103E 0F D8         02810       CLR <$08    List flag: don't re-list
1040 EC 8C 04      02820       LDD <BUFEND,PCR
1043 7E 8548       02830       JMP $8548   Go Edit
02840
1046               02850 FFLAG RMB 1       <>0 if match found,
02860 * also holds letter under cursor
1047               02870 BUFEND RMB 2      End of line in print buffer
1049               02880 LENTS  RMB 1       Length of target string
104A               02890 TARGET RMB 10     Buffer for Target string
1054               02900 ZEND   EQU .       End of program is here
02910
0F00               02920        END START  Exec address is at "START"
00000 TOTAL ERRORS
START 0F00
BUFEND 1047 DONE 0F82 FINDIT 0FF5 LENTS 1049 OK 0F66 TABLE 0F2A
CONT 0F9E EDIT 1035 FOUND 0FE2 LOOP1 0F77 PRESS 1010 TARGET 104A
CRSKEY 1026 FFLAG 1046 JUMP 0F57 MATCH1 0FC5 PRINT 0FB8 TEST 0FEA
CURSOR 0FFF FIND 0F5F KEYEND 1034 MATCH2 0FCD PUTHI 0F1E TITLE 0F5B
DELAY 102A FIND2 0F86 LENGTH 00F9 NXTLIN 0F8D SHOWIT 0FF2 ZEND 1054