Programming the Hi-Res Board ============================ There are 3 undocumented ports usable with the Model 4 Graphics Board. They are ports 140, 141 and 142. They control such various functions as enabling the mixed text/graphics mode, and controlling X,Y scrolling around the entire 32K of graphics memory (of which only 18.75K is actually displayed and used at the current time). First a discussion of the documented ports and their use; ports 128, 129, 130 and 131. Ports 128 and 129 are the x and y address ports, respectively. They select the byte on the graphics board to be read or written to. They do NOT select an individual point, but an entire byte of data out of the 32K of memory on the graphics board. The y address may vary from 0 to 255 (with 0 to 239 being displayable via BASICG - more later) and the x address may vary from 0 to 127 (with 0 to 79 displayable - again, more later). This enables you to examine the entire bank of graphics RAM ( 128x256 = 32K ). To read or write the byte selected, use port 130. The Basic statements A=INP(130) and OUT 130,A will read and write to that byte, respectively. The data shows up on the graphics screen as the bit image of the byte. This is the binary representation of the byte you send. E.G. - if you OUT the number 5 to port 130, it would "set" two points on the screen, because 5 is representated by "setting" bits 0 and 1 of a byte. Refer to your TRSDOS manual for a discussion of bits, bytes, and binary. This is a routine that will, in Basic, set any point on the screen: This is not a complete Basic routine, but can be used in a subroutine. No error checking is done. 10 REM X & Y HOLD THE X,Y COORDINATES OF THE POINT (X=0-639,Y=0-239) 20 OUT 128, X\8 '** SELECT X COORDINATE 30 OUT 129, Y '** SELECT Y COORDINATE 40 T=INP(130) '** GET DATA ALREADY THERE 50 OUT 130, T OR 2^(7-(X MOD 8)) '** MERGE REQUESTED BIT AND DISPLAY 60 RETURN '** RETURN FROM SUBROUTINE Line 20 outputs the requested x coordinate dividided by 8. This is because there are 8 bits in a byte, and the port selects a whole byte (8 "X" Pixels) Line 30 outputs the requested y coordinate directly to the board. No conversion is necessary Line 40 gets what ever is already displayed at that point, and saves it. Line 50 is the only complicated part: It takes what ever was already displayed at that point (saved in T) and "or's" it with the point you selected. (Please refer to your TRSDOS/BASIC manual for details on "or"-ing.). The equation is best explained part by part. The (X MOD 8) finds the remainder of the x address divided by 8 (remember we found the byte by using the quotient of x divided by 8). We then subtract this value from 7, and raise 2 to this number. Why? Because of the way the pixels are mapped. if we were to out put a 1 to port 130, to x,y address (port addresses) 0,0 - we would get 0 0 0 0 0 0 0 1 displayed (zero's standing for no point lit, a 1 standing for a "set" point) This is not what we want. We want 1 0 0 0 0 0 0 0 So, we take the remainder of x/8 - [ in our example of trying to set point 0,0 on the screen, a 0 would be output to 128 (0/8), and a 0 would be output to 129 (directly) ] - which is 0. Subtracting this number from 7 gives us 7. Raising two to this power yields 128 (2^7=128), which is what we want (a byte of "1 0 0 0 0 0 0 0" )!! Port 131 controls various aspects of the graphics board - the bits are mapped as follows: Bit # Description ===== ============ 0 - Turns the Graphics screen on and off: 1 = ON, 0 = OFF 1 - Controlls Video Waits: 1 = Wait, 0 = NO WAIT 2 - X "Clocking" Control: 1 = DECREMENT, 0 = INCREMENT 3 - Y "Clocking" Control: 1 = DECREMENT, 0 = INCREMENT 4 - X "Clocking" Control: 0 = CLOCK AFTER READ, 1 = NO CLOCKING 5 - Y "Clocking" Control: 0 = CLOCK AFTER READ, 1 = NO CLOCKING 6 - X "Clocking" Control: 0 = CLOCK AFTER WRITE, 1 = NO CLOCKING 7 - Y "Clocking" Control: 0 = CLOCK AFTER WRITE, 1 = NO CLOCKING Address clocking is a very valuable feature, and greatly speeds up graphics programs. Basicly it consists of this - you can program the graphics board to AUTOMATICALLY alter the x,y address so that you need not constantly be updating them with out's to ports 128 and 129. This cuts the number of commands needed to perform a function, and thus speeds up processing by a factor of almost three! Here is an example in Basic: We wish to "invert" the screen - make white points black, and black points white. We will need to read a byte from the graphics board, invert it, write it back out, and continue with the next byte. Thus we will need to ADD one to the y position after every WRITE. We don't want the x coordinate to do anything, we want the graphics screen displayed, and video waits on (why later) Thus the status byte we need is: Bit position# 7 6 5 4 3 2 1 0 Byte we need: 0 1 1 1 0 1 1 1 Understand why before you go on. This byte is 119 (2^6+2^5+2^4+2^2+2^1+2^0) decimal. So now we have all we need for our program. 10 OUT 131,119 '** SELECT FUNCTIONS WE NEED FROM STATUS REGISTER 20 FOR X=0 TO 79 '** X COORDINATE GOES FROM 0 TO 79 (BYTES, REMEMBER?) 30 OUT 128,X '** SELECT X COORDINATE 40 OUT 129,0 '** Y COORDINATE STARTS AT ZERO 50 FOR N=0 TO 239 '** NUMBER OF BYTES (Y COORDINATES DOWN THE SCREEN) 60 T=INP(130) '** GET BYTE TO REVERSE 70 OUT 130,(NOT T)AND 255'** OUTPUT REVERSED BIT IMAGE, SELECT NEXT BYTE 80 NEXT N '** CONTINUE UNTIL END OF "ROW" (240 BYTES) 90 NEXT X '** SELECT NEXT X ADDRESS Ignore the (NOT T) AND 255 if you don't understand how it "reverses" the bits (complements them). It does. The main point is that nowhere in the main loop (lines 50-80) did you have to output an X or Y address. Each new Y address was computed AUTOMATICALLY. Just like if you had written: 20 FOR X=0 TO 79 '** X GOES FROM 0 TO 79 BYTES 25 FOR Y=0 TO 239 '** Y GOES FROM 0 TO 239 30 OUT 128,X '** SELECT X ADDRESS 40 OUT 129,Y '** SELECT Y ADDRESS 60 T=INP(130) '** GET BYTE TO COMPLEMENT 70 OUT 130,(NOT T)AND 255'** "REVERSE" IT 80 NEXT Y '** CONTINUE WITH NEXT Y ADDRESS 90 NEXT X '** CONTUNUE WITH NEXT X ADDRESS They may look equally long, but the first only has two statements inside the main loop, while the second has four. The time spent adds up fast. Only one thing can access memory at one time. The Graphics Memory is trying to be accessed by TWO things all the time. Your routine making graphic designs and the Video Scanner, which is trying to display them on the screen. If you were to have the two happen at the same time (your routine getting the right of way), then the Video Scanner would have nothing to display. But the electron gun in your screen never stopps - if it has no data to tell it what to do, it sends "white". So, every time your routine is accessing graphics memory, it is forced to wait until the Scanner it finished with a "line". This slows down your routine. These waits are called Video Waits. They can be enabled or disabled (bit 1 of the status register, port 131). Disableing them increases the speed of your routine (because it doesn't have to wait), but at the price of a "snowy" screen. To demonstrate the speed advantage, I wrote a "clear screen routine". With waits enabled, it took about one second to clear the entire graphics screen. With them disables - it took less than 3/10th of a second!! UNDOCUMENTED PORTS ================== Ports 140 and 141 control X and Y scrolling of the displayed graphics memory. This enables you to draw BEYOND the limits of the screen (port addreses x=0 to 79 and Y=0 to 239 are limits under basic. Port addreses X=0 to 127 and Y=0 to 255 are usable and perfectly legal), and then scroll over to view them. The video screen acts as a window to a larger drawing area (a 640x240 window to a 1024x256 drawing area). These two ports control which portion of the larger area you see. The way they work is this: The number that is output to this port is a reference to the port address that will be the "zero reference" for the video screen. That sounds very complex, but this VERY easy to use. Say you output the number 10 to port 140 (the X scrolling port). The screen shifts to the left 10 units (80 pixels). If you then output an 11, the screen shifts over 1 more unit (8 pixels). The number output is absolute, not relative to what was previously output. Think of numbering the columns of x bytes (columns 0 thru 79) - the number output moves that column over to the "zero" position (the left edge of the screen for X, the top of the screen for Y). BASICG does NOT recognize the extra memory. EVEN IF you scroll the screen over, all Basicg commands still work with the old area (some of which has now moved out of view). Basicg also does not clear this extra memory, so when you scroll, garbage will come into view. Here is a program that moves a shape around the screen: 10 CLR:SCREEN:CLS '** INITIALIZE SCREEN 20 CIRCLE(320,120),100:CIRCLE(320,120),200 '** DRAW "DOUGHNUT" 30 PAINT (320,120),60 '** FILL IT 40 FOR X=0 TO 127 '** PREPARE TO SCROLL HORZ 50 OUT 140,X '** SCROLL IT 60 FOR T=0 TO 10:NEXT T '** PAUSE FOR A WHILE 70 NEXT X '** CONTINUE 80 FOR Y=0 TO 255 '** PREPARE TO SCROLL VERT 90 OUT 141,Y '** SCROLL IT 95 FOR T=0 TO 5:NEXT T '** PAUSE FOR A WHILE 100 NEXT Y '** CONTINUE 110 OUT 140,0:OUT 141,0 '** PUT SCREEN BACK TO NORMAL Watch this program run, and you will get a better idea of how these functions work. Remember, they do NOT affect the way the ports 128 & 129 address the graphics board - they only affect the way the graphics memory is displayed! The last port I will discuss is port 142. This port enables a mixed Text and Graphics mode. All graphics and text are visible on the same screen at the same time (in direct contradiction to the manual)! Where text and graphics overlap - the point is reversed. If something is printed over a block of white then that printing appears in "reverse video". In fact, this is the only way to get reverse video when this mode is active. All characters are displayable but reverse video characters will appear as normal ones. To enable this mode, perform an OUT 142,1. To go back to normal, perform an OUT 142,0. Note: the mixed text/graphics mode is only available when the graphics screen is selected (Basicg SCREEN 0, or OUT 131,1). This enables you to have text only, graphics only, and mixed text and graphics modes!! I will conclude this discussion with a short program that demonstrates all three of these undocumented ports: 10 CLR:OUT 142,1:SCREEN 0:PRINT CHR$(21); 20 CIRCLE(320,120),100:CIRCLE(320,120),200:PAINT(320,60),1,1 30 PRINT "This is a test of the undocumented ports on the Radio Shack" 40 PRINT@(10,25),"HIGH-RESOLUTION GRAPHICS BOARD"; 50 PRINT@(19,0),; 60 FOR N=0 TO 255:PRINT CHR$(0);CHR$(N);:NEXT N 70 T=0:FOR X=0 TO 127 80 OUT 140,X:OUT 141,(ABS(SIN(T))*120+240)MOD 256:T=T+.1 90 NEXT Y,X:GOTO 70 When doing machine language programs, using the OTIR,OTDR,INIR, and INDR commands in union with address clocking speeds things up considerably. Also turn video waits OFF whenever practical (the graphics screen isn't being displayed at the moment, etc...) If you have any questions or comments - please feel free to contact me. This documentation is complete as far as MY knowledge goes: if you have any further knowledge, please contact me and let the world know! (for instance, what do the other bits of port 142 do?) - Paul Bradshaw [72177,2032]