Page Index
- Do I have a GA or NGA Model 4????
- Model 4 POKEs
- Model 4 PEEKs
- Model 4 Keyboard PEEK Table
- Directly Access Model 4 Video
- Model 4 Graphics Board / Undocumented Ports
- Model 4 Video Locations
- Programming the Model 4 Function Keys
- Changing the Model 4 Speed
- Controlling the Model 4 Sound Card
- Special Model 4 BASIC Commands
Do I have a GA or NGA Model 4????
If your Model 4 never went in for service, the below can be an indicator. If your Model 4 was in for service, there is no guarantee that boards were not swapped, so the below might not hold true.
To check, flip your Model 4 onto its back so you can see the ports on the bottom.
POKEs
Caps Lock (TRSDOS 6.xx.xx):
Break Key (TRSDOS 6.xx.xx):
Cursor (TRSDOS 6.xx.xx):
PEEKs
Model Determination (TRSDOS 6.xx.xx):
= 5 if you are using a Model 4P
Version ID (TRSDOS 6.xx.xx):
Date (TRSDOS 6.xx.xx):
File System (TRSDOS 6.xx.xx):
BASIC Program Area (BASIC 01.01.01)
Model 4 Keyboard PEEK Table – Colin Dunn
In order to be able to PEEK these keyboard keys, you must first:
- If using BASIC: set HIMEM to F3FFH, and POKE location 120 with 134, and also do an OUT 132,134.
- If you’re using machine language: Disable the interrupts (DI), and then perform an OUT to port 132 with 134.
The above will make the keyboard and screen memory accessible. To reverse this condition, use:
- In BASIC: POKE 120,135:OUT 132,135. This will make normal RAM accessible and cancel out the use of keyboard and video memory.
- In machine language: Out to port 132 with a 135. Also, re-enable the interrupts to keep the type-ahead and real-time clock and any other interrupt task active.
If you program the keyboard and screen access in machine language, place no programs higher than location F3FFH. If you do, the video RAM will load over the program, and any attempts to jump, call, or use data in addresses above F3FFH will fail. JUMPs and CALLs will crash the SYSTEM!!!
This list of keyboard locations and values was compiled by Colin Dunn. This list will be useful for programmers looking to access the keyboard memory directly and write programs like keyboard drivers, games, etc.
Example: A=PEEK(&HF440) is the same in 4 mode as A=PEEK(14400) in the 3 mode.
Directly Access Model 4 Video – Colin Dunn
If you are frustrated on the Model 4 because you can’t directly access video memory, there is relief for you!!! You can do some spectacular video tricks in the 3 or 4 mode.
Model 3 mode
The 3 mode uses 1024 bytes of video memory addressed from locations 15360 to 16383. If you’re running on a model 4, you can have TWO pages of video RAM in 3 mode. This is useful for page-flipping animation or fast screen displays. I have used it to hide DOS messages when I want to make a pseudo-self-booting disk (contains DOS, but has no notice of the DOS)
That’s enough background, so I’ll get on with the explaining of Mod 3 mode video access!!
(This is how those 80X24 drivers for the 3 mode work. Printing at position 64 will be in the middle of the first line, so each line of screen is 80 print positions apart.)
(Note: to go back to graphic characters, use OUT 132,0 or OUT 132,128 )
Model 4 mode
You can do the direct screen poke trick in 4 mode. If you hated the pains of page switching in the 3 mode to use 80X24 access, the 4 mode can help you.
You MUST first execute a CLEAR,&HF3FF command before doing any of this!! If you don’t, the computer will crash!!!!
Now that you’ve set aside all that memory, you can start working on it. If you like to set up SYSRES modules, set the HIMEM pointer to &HF3FF first before loading SYS modules into memory. It is fatal to possibly overwrite them. I have not really tried SYSRES modules and direct screen access. I will post a message in the Model 4 Corner of the TBBS ISLAND when I get around to testing it.
Enough of those warnings!!! Here goes…
If you are using assembly language, don’t put data in address 120 decimal. You just load the A register with 134 and OUT (132),A to switch in video memory. YOU MUST DISABLE INTERRUPTS OR DOS SERVICE ROUTINES WILL STEAL THE VIDEO MEMORY OUT FROM UNDER YOUR PROGRAM!!!!!!!
Model 4 Graphics Board – Undocumented Ports
Programming the Hi-Res Board – Paul Bradshaw
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 ( 128×256 = 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:
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 Number: 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 NEEDED FROM STATUS REGISTER 20 FOR X=0 TO 79 '** X COORDINATE GOES FROM 0 TO 79 (BYTES) 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 COORDINATE 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 640×240 window to a 1024×256 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 "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…)
Additional Information
O.K. – The graphics board has all these neat features. But I can’t use them from within basicg (easily). Big deal, right? RIGHT! Because using these features is very easy, given a simple little subroutine to set things all up. You CAN make basicg recognize all that extra memory, and you CAN write basicg programs that draw with 1024×256 graphics! All you must do, is convince Basicg not to “throw away” the values of x between 640 and 1023. The same for the y values between 240 and 255. This is how you do it:
While doing a little detective work poking around basicg to see what made it tick, I found what appeared to be a data area that extended from X’8711′ to X’8787′. Upon further investigation, I was able to pin down the areas where basicg stored the VIEW coordinates (the limits for the currently defined graphics screen). I also discovered another interesting storage area which I’ll talk about at the end of this.
The addresses X’8735′ and X’8736′ store the first x coordinate (for the upper left corner). The addresses X’8737′ and X’8738′ stored the second x coordinate (for the lower right). The addresses X’8739′ and X’873A’ stored the frist Y coordinate (in TWO bytes!!), and like-wise the second was stored in X’873B’ and X’873C’. What I did was poke the proper values for a 1024×256 graphics screen in. But that wasn’t enough.
At addresses X’8784′ and X’8785′, I found the acceptable “column” numbers for the x coordinates (the port values, not the pixel values). I changed these to their proper X’00’ and X’7F’, respectively. At addresses X’8786′ and X’8787′, I found the “remainder” mask for the port values. These specified which bit in the byte was the “last acceptable” before it should ignore plotting that point. I set these to their proper X’00’ and X’80’. That was all that was necessary. Now all graphics commands (except VIEW) will operate on the WHOLE of the graphics memory. you may GET and PUT off the screen (but withing the 1024×256 limits), LINE, CIRCLE, PAINT, etc!! You could then use the ports 140 and 141 to scroll over and see the extra areas of the screen memory!
As an added bonus, the CLR command cleared the ENTIRE graphics memory as well. But the CLR was slower because of all that extra memory it was clearing (I had though it was slow to BEGIN with). Now for that extra storage area I told you about. I was the image of port 131 at X’871E’. Armed with the knowledge, I could reset the bit 1 (which controls video waits), and thus speed up all graphics substantially. To use the high-speed CLR, POKE &H871E,253. To go back to the normal mode (no snow), POKE &H871E,255. For really impressive results, when you want to clr the screen, execute the following:
POKE &H871E,254:CLR:POKE &H871E,255
This appears to erase the screen instantly with no snow, by turning off the graphics screen while it erases! Now that Basicg can instantly erase the screen (and speed up painting and circles when you are drawing when the screen is not displayed), and all graphics commands can operate over the whole range of the graphics memory, just think of the possibilities!!
Model 4 Video Locations – Colin Dunn
In order to be able to POKE/PEEK the video display in Model 4 mode, you must first:
- If using BASIC: set HIMEM to F3FFH, and POKE location 120 with 134, and also do an OUT 132,134.
- If you’re using machine language: Disable the interrupts (DI), and then perform an OUT to port 132 with 134.
The above will make the keyboard and screen memory accessible. To reverse this condition, use:
- In BASIC: POKE 120,135:OUT 132,135. This will make normal RAM accessible and cancel out the use of keyboard and video memory.
- In machine language: Out to port 132 with a 135. Also, re-enable the interrupts to keep the type-ahead and real-time clock and any other interrupt task active.
If you program the keyboard and screen access in machine language, place no programs higher than location F3FFH. If you do, the video RAM will load over the program, and any attempts to jump, call, or use data in addresses above F3FFH will fail. JUMPs and CALLs will crash the system!!!
The video memory extends from F800H to FF7FH (leaving 128 bytes at the top of memory untouched, but this limited storage has no practical use except for some machine language program variables and data areas).
Here’s the info on what addresses are for what line:
(the line numbers are in decimal, but the addresses are in hex)
The Model 4 uses the same character set as the Model 3 as long as the reverse video is turned off. If you wish to use reverse video, first send CHR$ code 16 to the display, then switch in the video memory. You can only access inverse video and POKE the data if you SET bit 7 of the data going to the display. Example: Send ASCII code to display with this assembler program:
LD A,41H
LD HL,F800H
LD (HL),A
The above puts the normal video “A” on the screen. If you want reverse video, use this:
LD A,41H ; A
SET 7,A
LD HL,F800H
LD (HL),A
You can also calculate the reverse video strings by adding 128 to each value to send to the screen.
***** N O T E *****
If you enable the reverse video, you *CANNOT* use the graphics characters. To disable the reverse video and enable the graphics, send a CHR$ code 17 to the screen.
Programming the Model 4 Function Keys – Colin Dunn
The Model 4 function keys are programmable…
In Model 3 mode:
F1 = 16875 F2 = 16876 F3 = 16883
POKE the above addresses with values for the F1, F2, and F3 keys…
If you use TRSDOS 6.2:
F1=0918H F2=091AH F3=091CH
SHIFT F1=0919H SHIFT F2=091BH SHIFT F3=091DH
Poke these from BASIC or change the values from DEBUG. You can save the configuration with the SYSGEN command.
Changing the Model 4 Speed – Colin Dunn
It is possible to use configurations of 4MHZ III mode or 2MHZ IV mode…
To use a FAST 3 mode, execute POKE 16912,104. If you plan to do disk access, return to 2MHZ or tell your DOS that the computer is at 4MHZ. (For LDOS, use the command: SYSTEM (FAST) at LDOS READY)
To use the SLOW 4 mode, use a SYSTEM (SLOW) at TRSDOS READY. Going back to FAST mode in 4 mode is just a SYSTEM (FAST) away. TRSDOS 6 automatically takes care of disk access delays.
You may wonder, WHY DOES DISK ACCESS NEED SLOWER SPEED???? Answer: If you access a disk and the computer is running too fast, the disk drives get bad commands. A disk can be wiped out by accessing disks too quickly!!!
Controlling the Model 4 Sound Card – Colin Dunn
The Model 4 SOUND BOARD command are generally disappointing. When you use the JCL, you only get 7 tones and 31 L-O-N-G durations. Not good for games. BASIC does the same things. Why didn’t RS include the PLAY command or a good SOUND command? By the way, the limited Sound command is accessed by SOUND T,D where: T=0 to 7 and D=0 to 31. Using a duration of 31 takes about 4-5 seconds to produce a tone. Worse yet, the tones don’t allow a musical scale.
The SOUND BOARD is accessed through port 144 (90 HEX). It is used the same way the tape port on the III is used for sound. (Note: 4P users don’t have to bother with port 144. Port 255 will do sound board access on the 4P since it lacks a cassette port. Here are some ideas on the use of the sound board:
Change the OUTS to port 144 in your favorite game programs. Find D3 FF sequences in the hex dump of your /CMD file. Change it to D3 90. Once you apply the patches, the sound goes to the Model 4 sound board.
Special Model 4 BASIC Commands – Colin Dunn
Have you ever felt lost in Model 4 BASIC?? Have you been wasting memory on MOD 3 routines which are built in commands in 4 mode? If so, read on!
The INTEGER DIVISION COMMAND
In 3 mode, you would do: A=INT(B/C) to get a remainder-free division.
In 4 mode, just do this: A=B\C. Save a couple bytes and a some typing.
INPUT$
Have you ever had this show up in your programs? 10 A$=INKEY$:IF A$=”” THEN 10
If so, save some memory! Use A$=INPUT$(1)!!!
Also, if you want password entry in a program, you simply use a$=INPUT$(X) where X is the number of characters to enter. All character codes are taken. There is no backspacing, and it won’t display anything on the screen.