Play online

You can play this game online using the JSBeeb emulator here:

http://tinyurl.com/zsyjvcq

How to play

Use Z and X to move the helicopter (green block in the thin version) left and right, and "shift" to thrust upward. Avoid the birds (red blocks) and collect coins (yellow blocks). Each coin you collect on a single trip doubles your bonus.

When you hand on the platform, the bonus is added to your score and zeroed, and you receive a new load of fuel. The aim of the game is simply to get the highest possible score.

If you run out of fuel (indicated by the red bar), you lose the ability to thrust upward, though you can still land if you're nimble enough. If you collide with a bird or miss the platform, you die. Press "space" to start a new game.

How to build

Building the resources requires python 2.7 with pygame. Type:

python gfx.py > gfx.s

Building the binary files requires atasm or equivalent:

http://atari.miribilist.com/atasm/

Type:

atasm -r gfx.s

atasm -r -DHACKADAY_1K=1 -DHACKADAY_2K5=0 copter.s -othin.bin

atasm -r -DHACKADAY_1K=0 -DHACKADAY_2K5=1 copter.s -ofat.bin

How to launch

Load the disk image "copter.ssd" into your hardware or emulator (we recommend BeebEm for this).

If using real hardware, set up the keyboard links to boot into graphics mode 2 (see below).

If using an emulator which doesn't support the keyboard links, change to mode 2 on startup by typing:

MODE 2

To run the "fat" version, type:

*LOAD GFX

*RUN FAT

To run the "thin" version, type:

*RUN THIN

BASIC scripts "GOFAT" and "GOTHIN" are provided to automate these steps. At startup, type:

CHAIN "GOFAT"

or:

CHAIN "GOTHIN"

Accessing hardware

On top of writing data to the display, we need to interact with the hardware in a couple of ways. The OS ROM is off limits, so we have to do this the old-fashioned way.

We poll for vblank by reading bit 1 of the system 6522 VIA interrupt status register at 0xfe4d. The vblank status is cleared by writing to the same register. We clear the vblank status immediately before the main loop to ensure we're in sync from the very first frame, as otherwise we see some flicker early on.

We scan the keyboard by disabling keyboard auto-scan at start of day, and then writing to and reading from the slow databus at address 0xfe4f. The (completely insane) annotated disassembly for Exile here:

http://www.level7.org.uk/miscellany/exile-disassembly.txt

was very helpful in figuring out how to do this.

Drawing sprites

The BBC Micro lacks hardware sprite support, so all our moving objects (birds, coins, the helicopter, the platform) need to be drawn to the framebuffer in software. This is made more exciting by the BBC's odd screen memory layout. Each byte contains two horizontally-adjacent pixels interleaved in bits (6,4,2,0) and (7,5,3,1), and pixel-pair byte addresses look like this:

0x000 0x008 0x010 ..

0x001 0x009 0x011 ..

0x002 0x00a 0x012 ..

0x003 0x00b 0x013 ..

0x004 0x00c 0x014 ..

0x005 0x00d 0x015 ..

0x006 0x00e 0x016 ..

0x007 0x00f 0x017 ..


0x280 0x288

0x281 0x289

0x282 0x28a

: : : : : :

Our sprites are all 7*8 pixels in size (allowing us to support odd x coordinates using pre-shifted copies). The function "plot" does the necessary setup and uses one of three kernels ("pad", "store" and "blend") to do the actual writing.

Blend is the most interesting kernel. It uses a per-pixel mask stored in the "spare" senior bit of each pixel (the BBC Micro only supports 8 colors, so only three bits are required for the full palette) to do pixel-accurate masking and hit detection.

Chasing the raster

The game runs in graphics mode 2, whose framebuffer consumes 20K of the 32K of available RAM. Double buffering is out of the question, so to get flicker-free graphics we must carefully manage the position of the raster. In summary:

  • The game runs "in a frame" at 50Hz.
  • Frame processing starts immediately at the start of vblank.
  • Coins and birds never overlap, and are designed to be self-erasing; the bird in particular is drawn padded with a pair...
Read more »