JBit

GameKit

Beginner
Part 1: Tiles
Part 2: Animation (1)
Part 3: Animation (2)

In this tutorial I assume that you have read the Beginner's Tutorial, studied the 6502 examples and written some snippets of code targeting the MicroIO chip.

Part 1: Tiles

The MIDP2 IO chip (called simply IO chip from now on) provides essentially the same level of control that professional game programmers have when writing 2D action games. This flexibility comes at a price: complexity.

Most of this complexity is usually at the initial stage of the program. How many objects are there? What is their shape and color? What about the playfield? How big is it? Does it scroll horizontally? Vertically? Not at all? All of these questions must be answered, answered of course using bytes... you can imagine that it is not going to be easy.

The "Empty" demo included in the GameKit provides a set of answers. On page 3, where you would normally write your program, a ready-made block of code configures the IO chip. Once the IO chip has been configured, the control is transfered to the code at 4:0.

The answers that the "Empty" program provide are designed to setup a playfield that will feel like the MicroIO display from the inside, but that will look prettier from the outside. Instead of displaying letters, symbols and numbers, you can display painted tiles chosen from the following set:

silk

They come from http://www.famfamfam.com/lab/icons/silk/.

The one at the top left corner is tile 1, the one right next to it is tile 2, and so on until the one at the bottom right corner that is tile 56.

So, is it just a matter of writing 3 into 2:42 to make a bulb appear? Unfortunately not. A direct link of cells to tiles is fine for a small grid, but with the IO chip you can define grids of thousands of tiles. Nothing prevents you from defining a grid of, say, 500x500 tiles (i.e. 25000 tiles) and show only a portion of them.

Having said that, the "Empty" program actually configures as many tiles as possible to fit on the display of your phone. For example, on a phone with a resolution of 176x220 pixels, 11 columns of 13 rows of tiles are available (each tile is 16x16 pixels).

So, how can you access a potentially large number of tiles with the IO chip? One at a time. The IO chip has the notion of the Current Tile. You can use the following cells:

Cell Description
2:87 The column of the Current Tile (initially 0, i.e. the leftmost column).
2:89 The row of the Current Tile (initially 0, i.e. the topmost row).
2:91 A cell linking to the tile itself.

After all this theory, let's do some practice. Load the "Empty" program, go to the Editor, select Save and enter a new name for it. Go to cell 4:0 and type the following:

LDA #2
STA 2:87
LDX #3
STX 2:91
INC 2:89
STX 2:91
INC 2:89
STA 2:91

Also, go to cell 20:5 and enter:

100 150 200

These three cells are used by the "Empty" program to configure the background (20:5 is red, 20:6 is green and 20:7 is blue).

Part 2: Animation (1)

Animation is essentially about timing and loops.

Programs so far have been "linear", i.e. after a few instructions, the program would reach a BRK and terminate. To be able to write animations, we need to be able to repeat a sequence of instructions over and over again. The easiest way to do it is to use JMP, for JuMP. It allows us to change the PC of the CPU, thus changing the address of the next instruction to execute.

With this knowledge, you might think of writing the following program (starting from 4:0; I assume that you have loaded the "Empty" demo first):

INC 2:91
DEC 2:91
JMP 4:0

Unfortunatelly, this program does not work. Well, it might work, but it is so unpredictable and inefficient that you really do not want to run it.

It is unpredictable, because JBit tries to run the program as fast as it can, and the actual speed varies a lot from phone to phone. My tests and the feedback that I have received suggest that JBit is able to simulate from around 10,000 instructions per second on slow phones to around 500.000 instructions per second on fast ones.

It is inefficient, because it would try to change the tile too often. Even on a slow phone, the tile would change thousands of times per second.

Actually, all this work would be wasted, because the IO chip would not even bother to keep up. The IO chip would update the tile eventually, but you have no idea how often. It might even be the case that the IO chip would use the same value more than once. What you would see is effectively a sampling of a very fast variable. The odds are not even 50%, as the value 0 is more likely.

There is a better way. When you are finished arranging the tiles, you can tell the IO chip that now is the time to update the display. You do so by writing 0 into 2:18. This has the nice side effect that JBit will suspend its CPU for a while and tell your phone that JBit is idle. Some phones might not care, but some might be able to switch their CPU into low-power mode in turn, draining less power from the battery of your phone.

So, this is a predictable and efficient version of the program above:

LDA #0
INC 2:91
STA 2:18
DEC 2:91
STA 2:18
JMP 4:2

Part 3: Animation (2)

Usually, we don't want to repeat a sequence of instructions forever, but just for a little while. We can do this by using BNE, for Branch if Not Equal. Branch instructions change the PC only if a specific condition is met. In the case of BNE, Not Equal is a bit misleading, as the condition really is Not Zero and it refers to the result of the instruction before the branch.

For example, the following sequence:

...
LDA #3
BNE 4:10
...

will continue to 4:10, while the following:

...
LDA #0
BNE 4:10
...

will continue to the next instruction after BNE.

There is a slight complication here. If you try to type in BNE, you will notice that the format is BNE r, not BNE n:n as you might expect.

The reason is that branches usually point to an instruction nearby and two bytes would often be wasted. The single byte operand is used as the number of bytes to skip forward (if between 0 and 127) or backward (if between 128 and 255, where 255 means 1, 254 means 2, etc...). Fortunately, there is no need for you to count them.

We will use the following code as an example:

LDX #30
LDA #0
STA 2:18    [1]
DEX
BNE <<1>>

We want the BNE instruction to point to STA 2:18, thus putting 0 into 2:18 thirty times and causing the VM to run for about 3 seconds (plus the time spent for initialization).

Load the "Empty" demo and type in the code starting from 4:0, leaving the operand of BNE to 0. Then switch to NAV ASM mode. The listing should look like this:

LDX #30
LDA #0
STA 2:18
DEX
BNE !!!!

The BNE is pointless (no matter the result of DEX, no branching takes place) and !!!! is a reminder that you probably meant to change it later on.

Here are the steps:

  1. Make sure that the cursor is on BNE !!!!
  2. Press 7. This sets an invisible marker on this address (4:8).
  3. Move the cursor to STA 2:18 (i.e., 4:4)
  4. Press 0. This swaps the cursor and the marker. The cursor is now on the BNE !!!! instruction and the invisible marker is now on the STA instruction.
  5. Select PutMark from the menu.

The listing should now look like this:

LDX #30
LDA #0
STA 2:18
DEX
BNE 4:4

With the cursor still on the BNE instruction, press 9. This moves the cursor to the address pointed by the operand and can be handy to check if the operands are correct.

As an exercise, type in the following:

LDY #10
LDX #8      [1]
LDA #2      [2]
STA 2:91
LDA #0
STA 2:18
DEX
BNE <<2>>
LDX #2
LDA #3      [3]
STA 2:91
LDA #0
STA 2:18
DEX
BNE <<3>>
DEY
BNE <<1>>

To be continued...