'=========================================================================== ' Subject: READING CHARACTER OFF SCREEN Date: 03-01-97 (12:28) ' Author: The ABC Programmer Code: QB, QBasic, PDS ' Origin: voxel@freenet.edmonton.ab.ca Packet: FAQS.ABC '=========================================================================== ' Question: ' How can I read a character and attribute off the screen (text), and can ' you explain how it works? ' Answer: ' The bytes are stored in memory, so to access them, you must first ' know where the screen memory address is (where h = hex): ' b800h:0000 is where we should start looking. ' b000h:0000 if you have a monochrome card/adapter. ' ' BASIC equivalent is: DEF SEG = &HB800 DEFINT A-Z DEF SEG = &HB800 ' &HB000 for mono (&H = Hex) ' Okay, we know where the information is stored... so now we have to ' get them. For BASIC, that command is PEEK (look it up in HELP). ' For one thing, we know that there are 2,000 possible locations on an 80x25 ' text screen. It's given that each location occupies one word (or two ' bytes). The first byte is the ASCII value of the character on the virtual ' screen, and the following is the attribute (colour?) of the character. ' I say colour? because it's not a definitive colour, it's actually the ' foreground and background colour kind of combined if you like to look at ' it that way... I'll go into how to decode the attribute later on. ' so let's see: b800h:0000 is a character ' b800h:0001 would be the attribute... and so on. ' Now with some fine tuning, we can come up with an algorithm to find ' the character and the attribute. ' Since there are 160 bytes per row (80 words = 2 bytes) ' - we can say that (Row% - 1) * 160 ' the second row starts at 160, then the next at 320... and so on. ' - and so the column is (Col% - 1) * 2 ' multiply by 2 because there are 2 bytes per location, and we want ' the character which is every even number. ' - That means (Col% - 1) * 2 + 1 would give us the attribute. ' - Minus 1 because the segment starts at 0000 but QB's row, column starts ' at (1,1) ' Putting this all together, we get the complete equation: ' ' CharAddress = (Row% - 1) * 160 + (Col% - 1) * 2 ' AttrAddress = (Row% - 1) * 160 + (Col% - 1) * 2 + 1 ' ' Using (Row%, Col%) ' The top left corner is (1,1) and the bottom right is (25,80) '------------------------ DEMO1 ----------------------------- Row% = 1 ' Let's read the upper left corner and return its character Col% = 1 ' and attribute if you want to as well. CLS COLOR 7, 0 LOCATE Row%, Col%: PRINT "Hello" Char = PEEK((Row% - 1) * 160 + (Col% - 1) * 2) ' Get first byte (even) Attr = PEEK((Row% - 1) * 160 + (Col% - 1) * 2 + 1) ' Get next byte (odd) ' Char is an ASCII value, so if you wanted the string equivalent: Char$ = CHR$(Char) PRINT "Character at (1,1) is: "; Char$ ForeGround = Attr MOD 16 BackGround = (Attr - ForeGround) / 16 ' How does the algorithm above work? ' Because only one byte is stored, the computer encodes the foreground ' and background colour into just one byte... so to undo what the computer ' has done we must first know what the heck it has done: ' Computer: Foreground = 12 BackGround = 3 ' So 3 * 16 + 12 = 60 ' ' Why 16? Because (0,1,2,3,...,15) = 16 different colours! ' ' Intelligent human being: Okay, now I'll reverse the evil procedure! ' ForeGround = 60 / 16 = 3 with Remainder 12 ' But luckily we have the function MOD (look it up in HELP) ' So 60 MOD 16 will yield the remainder we want, which it 12. ' ' Therefore, with some work: 60 - 12 = 3 * 16 (Learn your math) ' (60 - 12) / 16 = 3 ' ' So BackGround = (60 - ForeGround) / 16 = 3 ' or BackGround = (60 - ForeGround) MOD 15 = 3 PRINT "Attribute (Colour): "; ForeGround; ","; BackGround ' Let's try another one... '------------------------ DEMO2 ----------------------------- Row% = 7 ' Select new locations Col% = 10 COLOR 15, 5 LOCATE Row%, Col%: PRINT "Bye!" Char$ = CHR$(PEEK((Row% - 1) * 160 + (Col% - 1) * 2)) ' One step process Attr = PEEK((Row% - 1) * 160 + (Col% - 1) * 2 + 1) COLOR , 0 PRINT "Character at (7,10) is: "; Char$ ForeGround = Attr MOD 16 BackGround = (Attr - ForeGround) MOD 15 PRINT "Attribute (Colour): "; ForeGround; ","; BackGround END ' William Yu (voxel@freenet.edmonton.ab.ca) ' 03-01-97