In Mixed Graphics Modes
One of the problems of custom graphics modes is how to print characters on mode lines that are out of the usual range of that mode. For example, if we design a graphics mode such that the 30th line is mode two, we would get an error message if we attempted to print on that line. This is because the Atari thinks it is in the regular mode two, which allows only twelve lines of characters. We must therefore find another way to put the characters on the screen.
As you may already realize, the screen is just a type of window looking into a part of memory. If you change that memory, what you see on the screen also changes. The solution, therefore, is just to POKE the characters into the memory locations that correspond to the positions on the screen where we want them to appear.
Where Is The Screen In Memory?
Here is how to find the display list in memory:
But, you may well ask, what does this have to do with the screen memory, or display memory, as we will call it here? It just so happens that the first two memory locations in the display list point to the beginning of display memory in the following fashion:
DISMEM = PEEK(BEGIN) + PEEK(BEGIN + 1)*256
How Do We Calculate The Exact Memory locations To POKE Into?
Each mode line uses up a certain amount of memory. As you might guess, different modes use different amounts of memory per line. To be more exact:
MODE 0 1 2 3 4 5 6 7 8 MEM/LINE 40 20 20 10 10 20 20 40 40
So all we have to do is figure out how much memory is used before the mode line that we want to print on, and add that to DISMEM to determine where we want to start POKEing. As an example of how to do this, let's suppose we have a graphics mode with four lines of mode 1, 50 lines of mode seven, three lines of mode four, and three lines of mode two (4*8+50*2+3*4+3*16 = 32+100+12+48 = 192); and we want to print on the second line of mode two. Checking the table above, we go:
lines of mode 1 = 4 * 20 =
lines of mode 7 = 50 * 40 =
lines of mode 4 = 3 * 10 =
line of mode 2 = 1 * 20 =
(remember, we count only the lines above the one we want to print on)
|For a grand total of:||2130|
Therefore, memory location DISMEM + 2130 represents the first character in the second line of mode 2 for this particular mode. Memory location DISMEM + 2131 represents the second character, and so on up to DISMEM + 2149 for the 20th character.
We know that POKEing the appropriate value into the appropriate location will cause the desired character to appear at the desired screen location. Since we already know how to determine the appropriate memory location, we now ask:
How Do I Calculate The Appropriate Value For A Character?
It turns out that the value to POKE for a given character corresponds to the order in which the character descriptions are stored in ROM (see "Designing Your Own Character Sets" in Chapter 3). As a quick memory refresher:
For reverse characters, just add 128 to the value of the normal character.
My Brain Is In Hibernation; How Do I Convert A Character String To Its Appropriate Values?
I'll leave you with the following self-explanatory subroutine that will take the (predefined) character string PRINTME$ and the starting memory location STARTHERE (also predefined and equal to DISMEM + offset) and POKE PRINTME$ into the appropriate memory locations. Enjoy!
Note that (condition) equals 1 if the condition is true, 0 if it's not. Thus, X = 126:PRINT (X = 126) :PRINT(X = 127) will print a 1 followed by a 0.
Return to Table of Contents | Previous Section | Next Section