TICT TUTORIAL SERIES 1 - Part VI | © TI-Chess Team 2001-2003 |
Grayscale Text-Scroller with Background Image |
This tutorial will explain how to implement a Grayscale Text Scroller for the TI-89 and the TI-92p, where the text scrolls from bottom to top across a Background Image.
There are many ways to implement such a scroller. I have decided to explain the techniques behind using an oversized backbuffer (invisible screenbuffer). Of course, for plain text there exists character drawing routines in the AMS which support clipping (but they are very slow), so using the oversized backbuffer is more or less useless in this case. But the explained techniques can be used for any form of scrolling, too.
If you are new to TIGCC programming I suggest you examine file scroller_old.c first, because the old version is easier to understand. The new version (scroller.c) done by Lionel Debroux shows many advanced tricks including inline assembly to speed up the scroller.
When you try to scroll something you have one major problem: what should I do when I'll come near the borders of the screen ? To explain it in terms of the textscroller: How could I scroll the text this way that it scrolls softly in from below and scrolls softly out at the top without appearing and disappearing roughly ?
Screenshot of the Text Scroller after a few seconds
The presented scroller consists of a still image in the background and the text scrolls above it. To get more contrast for the text (to make it readable) the background image uses only the dark-gray plane and the light-gray plane gets completely filled.
Now to the trick used for the scrolling: the program allocates a buffer which is capable of holding a 160*108 pixels large bitmap. As you may guess it already the trick is to allocate more lines than lines fitting on the screen. In our case we allocate 8 more lines, because the program uses a 8-pixel high font. Drawing into the area of these invisible 8 lines, the program manages to let the text softly appear from below.
We don't use the AMS routine for drawing strings, DrawStr, because it is very slow, especially on AMS 2.xx.
To make the scrolling as fast as possible the allocated backbuffer will be used only for the text. This way the scrolling can be performed easily by just moving the complete content of the backbuffer line-by-line upwards. Whenever a complete line becomes completely visible a new line is drawn into the "invisible" part.
To combine now this "textplane" with the background and copy it into the the grayplanes the program uses a simple loop which takes one longword (4 bytes) from the textplane and one longword from the background image AND's them together and writes the result into the grayplanes.
(The type of the grayplanes differs depending on whether doublebuffering is used or not, see below).
Now we have scrolling. Nice isn't it ;-)
I know my above explanations are really rough and maybe not completely understandable, but I would suggest to examine the sourcecode for more details.
We have just managed to implement a grayscale scroller, but what do we see ? The result might flicker, depending on the scrolling speed.
So what causes these flickers ? The first source of these flickers is that the scroller runs with a fixed speed and the screen refreshing is done also with a fixed speed. If both speeds doesn't match in a special way you can get all kinds of flickers: constant ones, pumping ones etc.
This source can be fixed easily on all calcs. The screen refreshing and the frequency of interrupt 1 calls matches on HW1 calcs. By installing an own interrupt 1 handler we can "get in sync" with the screen refreshing. The sourcecode of this tutorial implements such a handler and shows its usage. On HW2 calcs another method have to be used, but it's even easier to synchronize with the screen refresh on HW2 calcs.
Now, starting from TIGCC 0.93, the updates I made in the grayscale support of TIGCCLIB "fix" the synchronization problem (GrayGetSwitchCount...).
For grayscales a special handler hooked on interrupt 1 is used. But grayscales are tricky: to get the imagination of grayscales 2 planes gets "flipped" fast. For a short period of time plane 0 is visible and than for a short period of time plane 1.
To get different shades of gray the time how long the planes are displayed differs from each other.
There exists also a general problem called "phasing", caused by the plane flipping mechanism itself.
The plane flipping mechanism for grayscales draws the single planes after each other to the visible screen to simulate real grayscales. Even if the content of both planes changes at the same time your eye will interpolate between one old plane and one new plane for a short period of time. In the case of our text scroller you might see the grayplane data for the light plane and the darkplane displaced by one line.
The only way to avoid "phasing" is to use doublebuffering grayscale, which is another topic. Starting from TIGCC 0.94, the grayscale support of TIGCCLIB supports doublebuffering. This program uses doublebuffering if USE_DOUBLEBUFFERING is defined.
Note that a define (USE_COMPRESSED_IMAGE) allows the use of a compressed image in the program. This decreases the size by about 600 bytes... The image is compressed using a kind of RLE. But it is even simpler than RLE, because only one byte is compressed: 0xFF, which is the most frequent byte in the data, far ahead any other byte (additionnally, 0x00 and 0xFF are the only bytes repeated multiple times in consecutive bytes). This way, we don't have to store "0xFF, number of 0xFFs, escape sequence byte", but just "number of 0xFFs, escape byte". The choice of 0x93 as an escape sequence byte is just due to the fact byte 0x93 is not present in the data...
Check the TICT HQ Website at http://tict.ticalc.org for more tutorials and software.More useful tips, tricks and hints can be found at our Messageboard at: http://pub26.ezboard.com/btichessteamhq.
Suggestions, bug reports and similar are VERY welcome (use our Messageboard for this!!).