Tiles in Basic I – Mode 0 and 1

One of the important topics that is really not that complicated if we discuss it step by step are the tile screen modes. If we check the official Commander X16 documentation there are following five tile modes available:
0 – 1 bit per pixel tiles– 16 colors
1 – 1 bit per pixel tiles– 256 colors
2 – 2 bits per pixel tiles
3 – 4 bits per pixel tiles
4  - 8 bits per pixel tiles

We have two layers at our disposal. We can think of layers as two screens above each other and each can have its own settings and memory location etc. Everything we will say about layer also applies to the other so let’s just focus on one at the moment. Each layer has 7 dedicated registers that define their appearance and behavior:
Layer 0 - $9F2D - $9F33
Layer 1 - $9F34 - $9F3A

However to be able to manipulate them we have to also look at few of the registers that affect behavior of both layers:


Register Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
9-0 $9F29 Video Current Field Sprite Enable Layer 1 Enable Layer 0 Enable - Chroma Disable Output Mode
10-0 $9F2A Horiz. Scale Active Display Horizontal Scale
11-0 $9F2B Vert. Scale Active Display Vertical Scale


We see we several interesting things in these registers. The most important ones for this topic are bits 4 and 5. We already covered Bit 6 in post about sprites. So what is the default mode after turning on Commander X16? Let’s check:

PRINT PEEK($9F29)
Returns 33 or 0010 0001 in binary

That tells us that Layer 0 is disabled (0 on bit 4 position) and that default text mode is using Layer 1 (bit 5 is set to 1). We also see that we are using mode 0 because all three bits 5-7 are set to 0.

Registers 10-0 and 11-0  are also very interesting because they define how much of the video screen we actually see. let's check their value after fresh start:

PRINT PEEK($9F2A)
PRINT PEEK($9F2B)

both return 128 or 1000 0000 in binary. What that means is that every pixel in memory will show as one pixel on screen or in other words if we have 128 in both registers we see maximum resolution of screen which is 80 x 60 characters. if we poke value 64 into them we scale the pixels by 2 so every pixel is expanded to 2 pixels, by poking 32 they are expanded by 4 and so on.

so if we do following:

POKE $9F2A,128
POKE $9F2B,64

we create 80 x 30 screen mode and so on. So in extreme by poking ones into these two registers we stretch just handful of pixels across the whole screen. Of course most of the values beyond e.g. 32 are not very useful except for some effects like below:





Since Layer 0 is disabled we can disregard it for now and study Layer 1 a little bit closer by checking seven dedicated registers. Last four are used for scrolling which we will not look at now, that is a topic that is covered in separate post.


Register Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
20 $9F34 Layer 1 - Config Map Height Map Width T256C Bitmap Mode Color Depth
21 $9F35 Layer 1 - Mapbase Map Base Address Bits 9 - 16
22 $9F36 Layer 1 - Tilebase Tile Base Address Bits 11 - 16 Height Width
23 $9F37 Layer 1 - H Scroll Horizontal Scroll Bits 0 - 7
24 $9F38 Layer 1 H Scroll - Horizontal Scroll Bits 8 - 11
25 $9F39 Layer 1 - V Scroll Vertical Scroll Bits 0 - 7
26 $9F3A Layer 1 - V Scroll - Vertical Scroll Bits 8 - 11


Starting with register 20, it defines the core characteristics of the layer of which the size is determined using two bits for both height and width and is defined in tiles with following values:

00 – 32 tiles in that direction
01 – 64 tiles in that direction
10 – 128 tiles in that direction
11 – 256 tiles in that direction

So that means that each layer can have 16 possible dimensions: 32 x 32 tiles, 32 x 64 tiles, 32 x 128 tiles etc. all the way up to 256 x 256 tiles which is quite large. If we add to this that each tile can be 8 or 16 pixels in each direction the possible size of each layer is very large.
Both these extreme dimensions are not very practical so in real life we will almost always work with smaller sizes

Bit 3 is also very important. It is used to distinguish between Mode 0 and 1 - 16 colors and 256 colors available per tile (or character). Let's check the defaults again:

PRINT PEEK($9F34)

returns 96 or 0110 000 in binary.

If we analyze what this value means it is clear that our default text mode is:
64 tiles high
128 tiles wide
Uses 16 color mode
Is not in graphics mode
Color depth is 00

Color depth has therefore 4 possible values:

00 - 1 bit per pixel
01 - 2 bits per pixel
10 - 4 bits per pixel
11 - 8 bits per pixel

Since the layer size is defined in tiles it is also important to understand what is the size of tiles. Tile sizes are defined in bits 0 and 1 of register 22.
Tile Height and Tile Width have following values:
0 – each tile is 8 pixels in that direction
1 – each tile is 16 pixels in size
This means that tiles can be 8x8, 8x16, 16x8 or 16x16 pixels.

At this time we have to also emphasize one very important fact:

Layers as they are defined in the memory do not determine what and how much of them are shown on the screen. That is determined in Display Composer which we will look at some other time.

Let’s again explore default state of the display at start and see if all we said above makes sense:

PRINT PEEK($9F36)
Returns 124 or 0111 1100

We see that bits 0 and 1 are both 0 meaning that by default we use 8 pixel X 8 pixel tiles, whic of course makes sense because we already know that Commander X16 fonts are 8x8 pixel big.

Register 21 and 22 contain pointers to different parts of video memory where data is stored. The following image explains why we need two pointers: one is pointing to tile definitions and the other to the display map which we sometimes refer to as screen memory.




The picture above also describes the fundamental difference between bitmap modes and tile modes.

In bitmap modes we manipulate pixels directly in the screen memory whereas in tile mode we store just indexes to tiles and tile definitions separately. This mode sounds much more complicated so there must be some real reasons why we do it this way. The answer is speed. We can define tiles once and then reap the same tile over and over on the screen by adding simple index which is 1-2 bytes instead of 8 bytes for 8x8 tiles or even 32 bytes for 16x16 tiles. If we use tiles VERA does the heavy lifting for us and we can use CPU cycles for something else. Of course bitmap modes are great for some other uses that just can’t be achieved with tiles for example math graphing, proportional text, graphical UI like GEOS, etc.
However most games use tile system with heavy use of hardware sprites to enable smooth movement of objects.

As we saw in the example above, text mode is just one type of Tile mode where each character is just 8x8 pixel tile.

Let’s continue to verify that all we said is true and check the content of these pointers for default screen.
PRINT PEEK($9F35) returns 0 which means that default Map Base is $00000. Which we know is true because we were using VPOKE to display characters in all other projects and games before. Remember the formula:

VPOKE 0, Y*256+X*2,CharCode

It now makes sense right?

It is important to mention that we can't choose just any address for the start of video memory. We only have 8 bits for it and 128K bytes of memory to address therefore we can only set bits 9-16 and therefore aligned to every 512 bytes or $200 hexadecimal. so our memory can start at 0 (default at startup), 512, 1024,1536, etc. or more conveniently in hex at $0000, $0200, $0400, etc.

Changing Tiles

What about the Tile Map, can we do something with it?

We saw above that PEEK($9F36) returns the value of Register 22. We also saw that bits 0 and 1 determine the size of tiles so we only have 6 bits remaining to define pointer to tile maps.

Looking at description of registers above we see that it contains bits 11-16 so we can only set address in increments of 2048 bytes or $800 hex. So where are we pointing at by default?

We put together results from registers above plus add 11 bits (0-10) of zeroes

%0111 11       00000000000

Or if we sort it properly:

%0    1111 1000     0000 0000

In hex this is $0F800

It means that our tiles or in this case character font should start at $0F800 in VRAM. And that is exactly where it is. VERA copies the data from ROM to that location. Alternatively we can make it also copy other character sets like ISO character set or lower case PETSCII.
For readers who don’t trust me let’s prove it by changing one of the characters with a smiley face. The drawing for 8x8 representation is below:



Luckily Commander X16 supports the binary numbers by default so we don’t need to translate to decimal numbers like in “old times”. Since @ character is first one in the character set with index 0 we can redefine it into smiley by simple eight VPOKEs like this:




And there we have it. Every time we type @ symbol now it is displayed as smiley face. In similar way we can redesign any of the 256 characters into some special symbols we might require or add letter from different alphabets.

Mode 1

Let’s now explore the Tile mode 1. It is very similar to the default Mode 0. The only difference is in how VERA translates the color attributes.

We can turn it on by simply setting Bit 3 of register 20 to 1 like this:

POKE $9F34,PEEK($9F34) OR %00001000

In Mode 0 only first 16 colors from palette are used but we can choose both background and text color so we have 256 different possibilities (some invisible when we use same color for background and foreground of course).

In Mode 1 all 256 colors from palette open up. Check the default colors in this link:


Using all these colors is extremely simple. We can change the text to any of the 256 colors by simply poking the color index into the attribute bye (it is always odd number) for each character using following formula:

VPOKE 0, Y*256+X*2+1,Color Index

We have the whole rainbow of characters at our disposal now. There is one problem though. Now we can’t control the background color. One workaround is to use inverse characters but the text is always black.
The other way is to remember that Color 0 is actually transparent and if we also remember that by default we are working on Layer 1 means that transparent color should show through the Layer 0 which is beneath the Layer 1. So all we need to do is turn on the Layer 0 and configure it in such a way that we can set different background colors that will show through.
Try doing it by yourself. If it doesn’t go below is short program that does it and generates following "art":



Link to source

Part II - Modes 2-4


Comments

Popular posts from this blog

Commander X16 Premium Keyboard

Hello VERA (BASIC vs C vs Assembly)

Default Palette