Programming Examples 16
Chapter 16:
Programming
Examples on the
Propeller Chip /
HYDRA
Well, that’s it, hopefully at this point you have some overall idea of what the Propeller chip
does and its relationship to the HYDRA’s hardware support around it. Next, we are going to
look at a number of demo programs to get you started and give you something to work with.
Hopefully, within hours you will have reverse engineered them all and will start making your
own crazy demos. At first as noted, you should start with Spin demos only then later try
some ASM, then even later try modifying the graphics driver itself and making variants of it
along with the tv driver. Just make sure to use my file naming and software conventions,
otherwise, you will quickly loose control of everything and start overwriting files. This chapter
is more of a hands-on chapter rather than a lot of theory. Here’s the general demos and code
bases we are going to play with:
Basic graphics programming
Game controller interfacing
Sound programming
EEPROM primer
Hybrid ASM/Spin programming and parameter passing
To begin with, here’s is a listing of all the basic Parallax Spin drivers and files that come with
the system that we will base our work on (all of these files are located in the SOURCES\ subdirectory):
MOUSE_ISO_010.SPIN
PS/2 Mouse driver, uses another cog when launched
KEYBOARD_ISO_010.SPIN PS/2 Keyboard driver, uses another cog when launched
TV_DRV_010.SPIN
NTSC/PAL TV driver, uses another cog when launched
VGA_DRV_010.SPIN
VGA 640×480 driver, uses another cog when launched
GRAPHICS_DRV_010.SPIN Graphics engine driver, is coupled to the TV driver, but
still uses another cog when launched
Game Programming for the Propeller Powered HYDRA
Page 319
II
Propeller Chip Architecture and Programming
Considering that most drivers run separately on their own cog, you can very quickly run out
of cogs! So keep this in mind – it might not we wise to run everything on a separate cog. In
fact, you may find it better to merge like operations into a “smart” driver, for example, a
single cog driver that does keyboard, mouse, and gamepad to save processing power, etc.
You will typically include both the graphics and tv drivers with each program along with the
mouse, gamepad, and keyboard drivers potentially. The following demos are simply to get
you started, there is going to be a fair amount of “reverse engineering” and code analysis on
your part to really understand things. I am going to give you a demo of everything important
and you can use these as a starting point. Later in Part III of the book we will develop more
demos, and skeleton drivers to perform higher performance graphics, sounds, and I/O. But,
the drivers illustrated in this chapter are more generic and based on Parallax’s original
drivers, thus we will refer to them as “reference” drivers and use them to model more
specific high-performance drivers later as needed.
16.1
Running the Demos
For each demo there will be one or more files that make up the demo. Typically there will be
a single “top level” file that might include other objects; simply run the demo from the
/SOURCES directory and any other files will be loaded by the Propeller IDE that are called out
in the top level file. Make sure to have your USB cable connected to your HYDRA and have
the Propeller IDE up and running with all drivers installed and functioning.
16.2
Programming Conventions and Filenaming
The following short rules and conventions were used by myself and the various “demo”
coders that developed for the HYDRA. Reviewing them will help you understand the naming
conventions as well as give you a set of conventions to follow (or not) that will help you keep
everything organized. Typically, you are going to develop only a few types of applications
and files:
Source code for games/demos in Spin/ASM usually
Drivers for the Propeller chip/HYDRA
PC Tools written in some RAD tool or C/C++/BASIC etc
Data files
The main goal of my programming conventions is that if all the files from EVERYONE on the
planet were dumped into a single directory not a single name collision would occur; this is
trivial if the correct measures are taken. For example, the following are bad ideas for file
names:
game.spin
' terrible!
driver2.asm
' crap!
Page 320 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
gamestuff.dat ' you gotta be kidding!
myobj.src
' ya right!
...and so on. These names are useless in large scale software development with more than
one person in the team. So we are going to use three simple tactics to create intelligent,
useful, informative names:
Tactic 1: All files must have a version suffix at the very end of the file name.
Tactic 2: All files must have a 2-4 letter “developer/library” prefix pre-pended to
them.
Tactic 3: All files must have intelligent (short) names, no spaces, but underscores
are okay.
Version Suffix
We have discussed this already, but there will be a 3 digit version code on EVERY single
source file. The format is:
MMm
The first two digits are the Major version number, the last digit is the Minor number, zeros
are used if there is no digit. This format allows us to version 0.1 to 99.9, some examples are:
version 1.3 = 013
version 1.0 = 010
version 0.5 = 005
version 10.8 = 108
...and so forth. You should append the version field to the end of all file names, example:
tv_driver_010.spin
graphics_api_020.asm
music_files_003.dat
' tv driver version 1.0
' graphics api version 2.0
' music data files version 0.3
...and so on.
In most cases, you will probably just use major version numbers, since minor version
numbers are useless really, but they are there if you need them. Typically, all your programs
will simply start with version 1.0.
Game Programming for the Propeller Powered HYDRA
Page 321
II
Propeller Chip Architecture and Programming
Developer “Tagging” with Code/Library Names
There are so many programmers working on so many projects that people are inevitably
going to think of the same names, thus to protect your code a great idea is to “code” a
unique sequence of characters into every single file name, typically at the front or end of the
file name works best. This will identify the coder/library and will make collisions nearly
impossible. For example, OpenGL uses “GL” in front of every function call; we are going to do
the same. For example, say you want to use “Bob Brown’s Game Engine” then you might use
BBGE or BGE for your code, and your files would look like this:
BGE_asteroids_demo_011.spin ' some spin game source
BGE_tv_driver_fast_texturing_001.spin
' a spin/asm driver
BGE_table_generator_021.CPP ' some external C++ for a tool
These are beautiful names, they indicate the developer/library “BGE” which we know is good
old Bob. Then the file names themselves are descriptive, finally there is a version code, so
these will never be confused or collided with. Of course, I hope everyone can find more
interesting names for the libraries. For example, “HEL” for the HYDRA Extreme Library –
which is mine, so that’s now taken!!!!
So every file you make has your developer prefix pre-pended to it along with the version
code. This includes all HYDRA stuff as well as your PC tools, data files, whatever. We want to
immediately be able to say “Bob” made that, it does this, and it’s version xxx.
Modifying Drivers
As far as core names for your games, tools, drivers, it’s up to you. However, if you do decide
to modify one of the “system” drivers written by Parallax, me, or Chip Gracey then please use
a name that is similar since it might end up on internet and will help people figure out its
origins. Additionally, in the source itself comment at the top of your source what driver it was
originally based on and what general modifications you made. For example, let’s say we want
to modify the graphics driver graphics_drv_010.spin and remove all the text stuff, add
better clipping, and support for textured triangles, then we might call the new driver:
HEL_FAST_GRAPHICS_DRV_010.SPIN
In this case, the name still indicates this is some kind of graphics driver, and this is the “HEL”
library (which we know whose that is!) and its version 1.0 of the driver. Then in the top of
the source we might find something like this:
{{HEL_FAST_GRAPHICS_DRV_010.SPIN - Written by Andre' LaMothe
Last modified 1.20.06, version 1.0
Page 322 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
This new graphics driver was originally based on Parallax's default graphics
driver GRAPHICS_DRV_010.SPIN.
I modified it to work faster, removed text support, and added texture mapping and
better object space clipping.}}
UNDER NO CIRCUMSTANCES should you modify an original driver then release
it with the same name on internet, it will cause confusion! Please make another
version of a default driver and update the version name with your own tag, these
files are like “original DNA” and only Parallax or myself will modify these
officially.
Deployment and Packaging
When you have completed a game or demo, another good idea is to always ZIP it up along
with a README.TXT file. Also, every single file for the demo should be in the ZIP. The reason
for this is the concept of a “package” – no one wants to hunt for a file, a version, etc. So
if you always deploy your demos/games as a ZIP with everything in there that the user needs
then he/she will be very happy. I almost have a hatred for open source projects since they
are so unorganized, nothing ever compiles, files are missing, etc. It’s like someone does all
this work and then no one else can appreciate it, so take time to “package” your projects,
the world will thank you. Here are some examples of how I do it:
Example 1: Single File
Say you made a game called HEL_centipede_023.SPIN and this is the only file. Then you
would create a zip and place the file in there:
HEL_centipede_game_01_20_06.ZIP
The ZIP does NOT necessarily have to have the same name as the file, since you might have
100 files in there, but you do want to put the developer tag on the zip as well as a DATE
code this time. Thus, when you upload another version maybe 2 days later then on the FTP
we would find:
HEL_centipede_game_01_20_06.ZIP
HEL_centipede_game_01_22_06.ZIP
This way we have backups and a record of all the work as well, and we can always see other
previous versions. Of course, you do NOT need to include standard drivers supplied by me or
Parallax, these are assumed, but anything you make must be in there.
Game Programming for the Propeller Powered HYDRA
Page 323
II
Propeller Chip Architecture and Programming
Example 2: Multiple Files
Let’s say that you have a game that is composed of a number of source files, a driver object,
a data file, and a C++ console application:
HEL_raycaster_034.spin
HEL_raycaster_data_010.spin
HEL_graphics_engine3D_021.spin
HEL_data_generator_ray_010.CPP
HEL_data_generator_ray_010.EXE
readme.txt
Then we would take all this and package it into a single ZIP with today’s date:
HEL_Raycaster_demo_01_20_06.ZIP
Now, there is a lot going on in this example, we have lots of files, and things are so complex
that we need a README.TXT to explain what’s what. Obviously, the readme is simple enough
where it doesn’t need a version or date, but it should explain things a bit, so someone that
opens this package doesn’t have to “reverse engineer” it and immediately can read what the
C++ files are for etc.
Now, let’s make a single change and see what happens. So 3 days from now, I decide to
rewrite the C++ code, and update the ray caster itself, so we change 2 files, once again, we
package all of them!
HEL_raycaster_035.spin
HEL_raycaster_data_010.spin
HEL_graphics_engine3D_021.spin
HEL_data_generator_ray_020.CPP
HEL_data_generator_ray_020.EXE
readme.txt
Now, we take it all and make a zip and if deployed on internet or on FTP we might see:
HEL_Raycaster_demo_01_20_06.ZIP
HEL_Raycaster_demo_01_23_06.ZIP
16.3
Graphics Programming
Basic graphics programming on the HYDRA is facilitated via the Parallax drivers
TV_DRV_010.SPIN and GRAPHICS_DRV_010.SPIN. The TV driver more or less
continually sends data out from the bitmap memory via the VSU unit and keeps the timing
Page 324 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
correct for the TV display. The graphics driver on the other hand is just a generic set of
graphics routines, not really tuned for speed or game programming, but more general
graphics and business rendering. You will immediately find the use of polar coordinates for
everything for example very slow and non-standard, but polar coordinates allow easier
rotation of simple circularly symmetrical objects, drawing of pie charts, etc. However, don’t
worry, you are free to write your own graphics drivers and or modify the current drivers.
With all that in mind, what I am going to do is show you a master demo that does all kinds
of stuff, and then briefly cover some of the details of this implementation of
GRAPHICS_DRV_010.SPIN. Although, we don’t want to spend too much time on the
generic reference drivers since you will inevitably re-write the drivers completely, or strip
them down since they not really designed for “game/graphics” rendering, but they are great
to get some demos up and running and use to develop demo programs quickly. Later in Part
III of the book we will develop a number of tile engines and other graphics drivers that are
more specific, but it’s very important that you follow the underlying principles of the Parallax
reference drivers since they are indicative of the kinds of issues and design decisions that
must be made when designing TV and graphics drivers in general, thus they are a good
“model” to begin with.
16.3.1
Master Graphics Demo – Graphics_Demo_010.SPIN
Figure 16:1
The Master Graphics Demo in Action
Figure 16:1 is a screen shot of the master graphics demo in action (written by Chip Gracey).
It doesn’t show every single function that the graphics driver GRAPHICS_DRV_010.SPIN
supports, but it gives you an idea of what the driver can do. To run the demo, follow these
steps:
Step 1: Load the file “GRAPHICS_DEMO_010.SPIN” into the Propeller IDE from the
directory CD_ROOT:\HYDRA\SOURCES\.
Game Programming for the Propeller Powered HYDRA
Page 325
II
Propeller Chip Architecture and Programming
Step 2: Press the F10 or F11 button to program the Propeller chip and start the demo.
The demo shows off rotation, sprites, use of multiple colors, text, scaling, rotation, and
numerous other effects.
16.3.2
TV and Graphics Drivers
There are two primary reference drivers that make all the graphics happen on the Propeller
chip and the HYDRA respectively, they are the NTSC/PAL TV driver) and the Graphics driver
itself, both of which are purely software and you don’t have to use if you do not wish to, but
give us a way to get something on the screen quickly. However, for now I suggest using
these for your first demos and games and then later you can re-write the Graphics driver and
potentially the NTSC/PAL driver yourself.
The NTSC/PAL driver is very low-level and primarily responsible for feeding TV with video
data via the VSU, thus the NTSC/PAL driver TV_DRV_010.SPIN is primarily a timing chain
state machine that drives the NTSC/PAL TV display. If you review the code you will find all
kinds of interested things, the first is that at the top of the file there is a number of constants
and parameters:
CON
fntsc
lntsc
sntsc
= 3_579_545
= 3640
= 624
'NTSC color frequency
'NTSC color cycles per line * 16
'NTSC color cycles per sync * 16
fpal
lpal
spal
= 4_433_618
= 4540
= 848
'PAL color frequency
'PAL color cycles per line * 16
'PAL color cycles per sync * 16
paramcount
colortable
= 14
= $180
'Start of colortable inside cog
The driver code continues on for many pages, then at the end there is a listing that describes
the “TV Parameters” list. This is a list of 14 LONGs that you pass to the TV driver when you
initialize it (the driver is totally programmable); through these parameters you tell the driver
where video RAM is, the color table, the character table, the screen size, the origin, and a
number of other settings. For your convenience here’s the TV parameters explanations pulled
from the source file for your review (take a few moments and peruse the listing):
''VAR
''
'' long tv_status
'' long tv_enable
'' long tv_pins
'TV parameters - 14 contiguous longs
'0/1/2 = off/invisible/visible
'0/non-0 = off/on
'%pppmmmm = pin group, pin group mode
Page 326 Game Programming for the Propeller Powered HYDRA
read-only
write-only
write-only
Programming Examples 16
'' long tv_mode
'%ccip = chroma, interlace, ntsc/pal
write-only
'' long tv_screen
'pointer to screen (words)
write-only
'' long tv_colors
'pointer to colors (longs)
write-only
'' long tv_ht
'horizontal tiles
write-only
'' long tv_vt
'vertical tiles
write-only
'' long tv_hx
'horizontal tile expansion
write-only
'' long tv_vx
'vertical tile expansion
write-only
'' long tv_ho
'horizontal offset
write-only
'' long tv_vo
'vertical offset
write-only
'' long tv_broadcast 'broadcast frequency (Hz)
write-only
'' long tv_auralcog 'aural fm cog
write-only
''
''The preceding VAR section may be copied into your code.
''After setting variables, do start(@tv_status) to start driver.
''
''All parameters are reloaded each superframe, allowing you to make live
''changes. To minimize flicker, correlate changes with tv_status.
''
''Experimentation may be required to optimize some parameters.
''
''Parameter descriptions:
'' _________
'' tv_status
''
''
driver sets this to indicate status:
''
0: driver disabled (tv_enable = 0 or CLKFREQ < requirement)
''
1: currently outputting invisible sync data
''
2: currently outputting visible screen data
'' _________
'' tv_enable
''
''
0: disable (pins will be driven low, reduces power)
''
non-0: enable
'' _______
'' tv_pins
''
''
bits 6..4 select pin group:
''
%000: pins 7..0
''
%001: pins 15..8
''
%010: pins 23..16
''
%011: pins 31..24
''
%100: pins 39..32
''
%101: pins 47..40
''
%110: pins 55..48
''
%111: pins 63..56
''
''
bits 3..0 select pin group mode:
''
%0000: %0000_0111
baseband
Game Programming for the Propeller Powered HYDRA
Page 327
II
Propeller Chip Architecture and Programming
''
%0001: %0000_0111
broadcast
''
%0010: %0000_1111
baseband + chroma
''
%0011: %0000_1111
broadcast + aural
''
%0100: %0111_0000
baseband
''
%0101: %0111_0000
broadcast
''
%0110: %1111_0000
baseband + chroma
''
%0111: %1111_0000
broadcast + aural
''
%1000: %0111_0111
broadcast
baseband
''
%1001: %0111_0111
baseband
broadcast
''
%1010: %0111_1111
broadcast
baseband + chroma
''
%1011: %0111_1111
baseband
broadcast + aural
''
%1100: %1111_0111
broadcast + aural
baseband
''
%1101: %1111_0111
baseband + chroma
broadcast
''
%1110: %1111_1111
broadcast + aural
baseband + chroma
''
%1111: %1111_1111
baseband + chroma
broadcast + aural
''
----------------------------------------------------------''
active pins
top nibble
bottom nibble
''
''
the baseband signal nibble is arranged as:
''
bit 3: chroma signal for s-video (attach via 560-ohm resistor)
''
bits 2..0: baseband video (sum 270/560/1100-ohm resistors to form 75-ohm
''
1V signal)
''
''
the broadcast signal nibble is arranged as:
''
bit 3: aural subcarrier (sum 560-ohm resistor into network below)
''
bits 2..0: visual carrier (sum 270/560/1100-ohm resistors to form 75-ohm
''
1V signal)
'' _______
'' tv_mode
''
''
bit 3 controls chroma mixing into broadcast:
''
0: mix chroma into broadcast (color)
''
1: strip chroma from broadcast (black/white)
''
''
bit 2 controls chroma mixing into baseband:
''
0: mix chroma into baseband (composite color)
''
1: strip chroma from baseband (black/white or s-video)
''
''
bit 1 controls interlace:
''
0: progressive scan (243 display lines for NTSC, 286 for PAL)
''
less flicker, good for motion
''
1: interlaced scan (486 display lines for NTSC, 572 for PAL)
''
doubles the vertical display lines, good for text
''
''
bit 0 selects NTSC or PAL format
''
0: NTSC
''
3016 horizontal display ticks
''
243 or 486 (interlaced) vertical display lines
Page 328 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
CLKFREQ must be at least 14_318_180 (4 * 3_579_545 Hz)*
1: PAL
3692 horizontal display ticks
286 or 572 (interlaced) vertical display lines
CLKFREQ must be at least 17_734_472 (4 * 4_433_618 Hz)*
* driver will disable itself while CLKFREQ is below requirement
_________
tv_screen
pointer to words which define screen contents (left-to-right, top-to-bottom)
number of words must be tv_ht * tv_vt
each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup
ptr
bits 15..10: select the colorset* for the associated 16 * 16 pixel tile
bits 9..0: select the pixelgroup** address %ppppppppppcccc00
(p=address, c=0..15)
* colorsets are longs which each define four 8-bit colors
** pixelgroups are 16 longs which define (left-to-right, top-to-bottom)
the 2-bit (four color) pixels that make up a 16 * 16 pixel tile
_________
tv_colors
pointer to longs which define colorsets
number of longs must be 1..64
each long has four 8-bit fields which define colors for 2-bit
(four color) pixels
first long's bottom color is also used as the screen background color
8-bit color fields are as follows:
bits 7..4: chroma data (0..15 = blue..green..red..)*
bit 3: controls chroma modulation (0=off, 1=on)
bits 2..0: 3-bit luminance level:
values 0..1: reserved for sync - don't use
values 2..7: valid luminance range, modulation adds/subtracts 1
(beware of 7)
* because of TV's limitations, it doesn't look good when chroma changes
abruptly - rather, use luminance - change chroma only against a black or
white background for best appearance
_____
tv_ht
horizontal number of 16 * 16 pixel tiles - must be at least 1
practical limit is 40 for NTSC, 50 for PAL
_____
tv_vt
Game Programming for the Propeller Powered HYDRA
Page 329
II
Propeller Chip Architecture and Programming
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
''
vertical number of 16 * 16 pixel tiles - must be at least 1
practical limit is 13 for NTSC, 15 for PAL (26/30 max for interlaced
NTSC/PAL)
_____
tv_hx
horizontal tile expansion factor - must be at least 3 for NTSC, 4 for PAL
make sure 16 * tv_ht * tv_hx + ||tv_ho + 32 is less than the horizontal
display ticks
_____
tv_vx
vertical tile expansion factor - must be at least 1
make sure 16 * tv_vt * tv_vx + ||tv_vo + 1 is less than the display lines
_____
tv_ho
horizontal offset in ticks - pos/neg value (0 for centered image)
shifts the display right/left
_____
tv_vo
vertical offset in lines - pos/neg value (0 for centered image)
shifts the display up/down
____________
tv_broadcast
broadcast frequency expressed in Hz (ie channel 2 is 55_250_000)
if 0, modulator is turned off - saves power
broadcasting requires CLKFREQ to be at least 16_000_000
while CLKFREQ is below 16_000_000, modulator will be turned off
___________
tv_auralcog
selects cog to supply aural fm signal - 0..7
uses ctra pll output from selected cog
in NTSC, the offset frequency must be 4.5MHz and the max bandwidth +-25kHz
in PAL, the offset frequency is and max bandwidth vary by PAL type
Page 330 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
Considering this massive list of possibilities there is a lot this driver can do and probably why
you do not want to re-write it at first, but use it as-is then later potentially re-write if you
need to free up memory and or have it work in other ways with memory or something that
are more conducive to your games’ architecture. However, that being said, I think that in
most cases we probably can use this driver for 50% of our games and demos. Still, the
GRAPHICS_DRV_010.SPIN definitely will need customizing for more advanced games and
at very least to cut out all the business graphics and generalization it has that we don’t need
for games. Alas, when it comes time to start making changes you will start with the
GRAPHICS_DRV_010.SPIN driver at first, but at first just use them as-is to get things
going!
A Single Graphics Tile
Figure 16:2
In any event, the TV driver runs on a cog by itself and simply feeds the TV display with video
data. The video data comes from an “on-screen” bitmap buffer in the shared 32K memory
that is 2 bits per pixel, supports 4 colors, and is contiguous, but has a very strange memory
mapping which we will get to shortly. The size of the bitmap buffer is related to the number
of tiles you decide to run the TV in horizontally and vertically. The size of a tile is always
Game Programming for the Propeller Powered HYDRA
Page 331
II
Propeller Chip Architecture and Programming
16×16 pixels, that is, a single tile is constructed of 16 LONGs where each LONG is 32 bits
and supports 16 pixels at 2 bits per pixel, so this works out nicely. This is shown in Figure
16:2.
Therefore, the TV driver really is a tile-mapped system consisting of M-tiles horizontally
(columns, referred to as TV_HT in the TV driver), and N-tiles vertically (rows,
referred to as TV_VT in the TV driver) where each tile is 16×16 pixels, this is the actual
memory for the bitmap and referred to as the “Tile Bitmap Memory” or “TBM.” This is
shown in Figure 16:3.
The Tile Bitmap Memory (TBM)
Page 332 Game Programming for the Propeller Powered HYDRA
Figure 16:3
Programming Examples 16
Tile Pointer Map (TPM) pointing to the
Tile Bitmap Memory (TBM) and
Tile Colorset Table (TCT) with 1:1 organization
Figure 16:4
However, there is one more level of indirection! The memory is tile mapped like this and
referenced as described, but there is a “Tile Pointer Map” or “TPM” which is a 2D array
with the same M×N dimensions as shown in Figure 16:4. Each entry in the TPM is a single
16-bit WORD which contains both a pointer to the tile’s bits in bitmap memory along with an
index into the “Tile Colorset Table” or “TCT.” The Tile Colorset Table is an array of 64
LONGs, where each 32-bit LONG represents 4 colors each (8 bits per color), these colors are
used for the tile in question. Thus each tile can have 4 colors each out of a set of 64
Game Programming for the Propeller Powered HYDRA
Page 333
II
Propeller Chip Architecture and Programming
potential “Color Sets.” The organization of each Tile Pointer Map entry is shown below in
Figure 16:5 (paraphrased from the driver listing above):
The Bit Encoding of the Tile Pointer Map
(TV_Screen) in Detail
Figure 16:5
Each 16-bit WORD from the Tile Pointer Map (TV_Screen in the TV driver) array has two
bitfields:
A 6-bit index (0..63) into the Tile Colorset Table that indicates which Color Set
(a single LONG) of 4 colors to use for the tile.
A 10-bit pointer into the Tile Bitmap Memory which must be on a 64-LONG
boundary, this 10-bit value is augmented in the actual addressing and is turned into
a 16-bit address as shown below.
Bits 15..10: Select the Color Set for the associated 16×16 bitmap tile to use. Remember
each tile is build of 16×16 pixels, where each pixel is 2 bits, each 2 bits refers to 4 colors,
these colors (Color Set) are actually a single LONG pointed to by this 6-bit index. The format
of the Color Set is 4 BYTEs, each is one color, each is in the standard color format discussed
in the VSU discussions.
Page 334 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
Bits 9..0: Pointer bits to the Tile Bitmap data where these 10 bits form the upper 10 bits of
the final 16-bit address augmented as shown in Figure 16:6.
Close-up of the Bit Encoding of a Tile Pointer Map Entry
Figure 16:6
Referring the encoding above and Figure 16:5 as well, the bottom line is that each Tile
Pointer Map entry (TV_Screen WORD) points to the bitmap data and the color data for each
tile. The color part is easy: the upper 6 bits are an index into the Tile Colorset Table, simple
as that. But the lower 10 bits that form the pointer to the bitmap data are a little more
complex: you don’t give the actual address in these 10 bits, but you give the address to the
16-LONG block or 64-BYTE block, thus you can think of these 10 bits as the upper 10 bits of
a 16-bit address where the lower 6 bits MUST be 0. That is, they will always refer to a block
of 64 BYTEs or 16 LONGs since the addressing in the TV driver simply shifts these bits 6
places to the left and then manipulates the lower 6 bits during its addressing, but the “base”
address you supply as the 10 bits is a 64 BYTE or 16 LONG block where the bitmap is.
This is a very cool feature and allows you to either write directly into the bitmap tile memory
with each tile pointer pointing into its respective tile bitmap OR you can use the tile pointer
memory to point to the SAME bitmap. This way you can implement either full bitmap or
character graphics. For example, if you just want to do graphics, sprites, lines, etc. then you
need a stardard bitmap set up, so what you would do is decide on the size and number of
tiles of your bitmap screen, say 16×12 tiles (256×192 pixels), then in the tile pointer map
you would point each pointer directly to its 1:1 representative tile in memory and that would
be the last time you mess with the tile pointer map. Then all you do is update the tile
graphics memory map. This is shown in Figure 16:7, where the Tile Pointer Map is being
used as a Character Map and each pointer points to the start of a character in memory
facilitating character modes.
On the other hand, if you are going to primarily be doing “classic” tile graphics, then you
can have your “tiles” in memory wherever you wish.
Game Programming for the Propeller Powered HYDRA
Page 335
II
Propeller Chip Architecture and Programming
The Tile Pointer Map being used as a Character Map
Figure 16:7
Tiles don’t need to be contiguous in any way since you aren’t going to use any of the raster
graphics routines for lines, etc., the only constraint is that the tile bitmaps are 16×16 in the
proper format (16 LONGs per bitmap, each LONG represents 16 pixels of 2 bits per pixel).
Then you simply point your tile pointer map entries to these tile entries. This way you need
only update the tile pointer map and instantly the bitmaps would change on screen! For
example, to implement a character mode you would point each entry in the tile pointer map
to the SPACE character in the ROM (character 32) and you would see a blank screen, then if
you wanted an “A” to show up in the top left corner of the screen you would point the tile
pointer map entries to the “A” bitmap entry in the character set in the ROM at $8000 – this is
why each character is made of 16 LONGs, where each LONG represents (16) 2-bit pixels.
Then the trick is to only turn on certain colors in the “color table” so that only the “A” shows
up. If you recall there are TWO characters compressed into each ROM character location
(more on this later).
Page 336 Game Programming for the Propeller Powered HYDRA
Programming Examples 16
A Character in the Character ROM located at $8000
Figure 16:8
Game Programming for the Propeller Powered HYDRA
Page 337
II
Propeller Chip Architecture and Programming
The only problem with pointing the tile pointer map to a character in the character ROM is
that we need to “stack” two standard bitmap tiles since the characters in the ROM are 16
pixels wide by 32 pixels tall, but the TV driver assumes 16×16 pixel tiles. Therefore we
need to bitmap tiles to point to a single character definition in ROM, this is shown in Figure
16:8 (the “A” and “@” characters are overlaid/encoded as a pair in this example). This is a
bit of a bummer, since it’s nice to have one character per one tile, but the character set was
made tall to support some extra drawing and schematic characters, so if you want to use it
then you must use two tile pointer map entries to point to the top and bottom of the tile
pointer map to the character definition LONGs in the ROM lookup at $8000.
Therefore, at the end of the day, if you set up a tile map of 16×12 tiles where each tile is
16×16 pixels (by definition) then if you want to use the built-in ROM character set (which is
very tall at 16×32), you are going to only be able to draw 16 columns by 6 rows since it
takes 2 characters stacked to display the super-tall 16×32 character, and this cuts your rows
down by half. Therefore, you might want to make your own 8×8 character sets etc. Of
course, the graphics driver actually has a bitmap character engine that can draw very small
characters, but it is 100× slower literally than just pointing the tile point map to a character
definition in ROM.
16.3.2.1
Video Memory Mapping and Organization
The actual organization of the Tile Bitmap Memory and the Tile Pointer Map are a bit
tricky, so we are going to discuss that in a moment, but first let’s talk about animation and
double buffering. The TV driver supports a “double buffered” architecture, that is you
draw on an “off-screen” buffer and the TV driver renders an “on-screen” buffer.
Therefore, on start-up you tell the TV driver the address of the on-screen buffer only
(actually you do this indirectly through the Tile Pointer Map), the off-screen buffer is
manipulated by the Graphics driver and it’s the job of the Graphics driver to “copy” the
contents of the off-screen buffer to the on-screen buffer. Therefore, there is no coupling
between the TV and Graphics drivers other than if you want to see something then you need
to copy it into the on-screen buffer since this is the only thing the TV driver renders. The
relationship between the buffers and the drivers is shown in Figure 16:9.
The cool thing about this is that you can write your own “graphics” driver fairly easily, you
just have to remember that to “see” anything you have to have a function that copies the
contents of your off-screen bitmap data into the on-screen bitmap data which the TV driver
is always rendering. Thus, with the off-screen and on-screen buffers you can implement
standard double-buffered flicker-free animation.
Page 338 Game Programming for the Propeller Powered HYDRA
© Copyright 2026 Paperzz