ColecoVision#
Open 8bitworkshop IDE
Click here to program the ColecoVision in the 8bitworkshop IDE now!
ColecoVision Specifications#
- Lifespan
1982-1985
- Media
ROM cartridge
- CPU
Zilog Z80
- Memory
16K video RAM, 1K work RAM
- Controllers
two joystick/keypad controllers
- Best-selling game
Donkey Kong (pack-in)
ColecoVision game console
History#
Originally founded as The Connecticut Leather Company, Coleco Industries sold goods like swimming pools and snowmobiles throughout the 1960s. In 1976, it introduced the Telstar console, which used the AY-3-8500 "Ball & Paddle" chip to play variations of Pong. There were difficulties, like a last-minute FCC violation which required the intervention of Ralph Baer, Magnavox, and a ferrite toroid. Coleco would lose 22ドル million on the Telstar.
Eric Bromley designed a new programmable game system, but RAM was not yet cheap enough for a mass-market product. When prices came down, Coleco’s second console – stubbornly dubbed the ColecoVision – debuted in the summer of 1982. It was designed to deliver arcade experiences in the home, and so having a smash arcade hit would be critical to success.
Seeking game licenses, Bromley visited Nintendo president Hiroshi Yamauchi in Kyoto. While searching for the office bathroom, he discovered a Donkey Kong cabinet in a hallway. The game was not yet well known in the West, and had not yet been discovered by Coleco’s rival Atari. Coleco negotiated a deal for a 200,000ドル advance and a 2ドル per unit royalty, delivered on a cocktail napkin – which was saved from the metaphorical trash can by a last-minute appeal to Yamauchi’s daughter, Yoko.
The pack-in Donkey Kong cartridge was impressively faithful to the original. Coleco would sell around two million consoles and publish 145 cartridge titles – including Zaxxon, Gorf, Burger Time, and many lesser-known arcade ports – over the next three years.
The video game crash of 1983 took Coleco’s focus back toward traditional toys like the Cabbage Patch Kids dolls. But due to several missteps, including the poor reception of the Adam computer and talking ALF dolls, the company would file for Chapter 11 bankruptcy five years later.
Hardware#
Unlike the Atari 2600, which features two pieces of custom silicon, the ColecoVision uses off-the-shelf components:
CPU : Zilog Z80A (NEC version) at 3.58 MHz
Video : Texas Instruments TMS9928A Video Display Controller
Sound : Texas Instruments SN76489A Digital Complex Sound Generator
Video RAM : 16 KB
General-Purpose RAM : 1 KB
ROM BIOS : 8 KB
A game cartridge plugs into the top of the unit, and it contains anywhere from 8 to 32 KB of ROM storage.
The ColecoVision also contains a BIOS ROM, a preprogrammed bit of code which runs when the console powers up or is reset. It displays a copyright notice for 12 seconds, and then transfers control to the game cartridge if one is present. The BIOS also contains bitmap fonts and various utility routines.
There is also an Expansion Module Interface at the front of the unit which can accept various plug-in modules to add functionality. Several different modules were produced during the console’s lifecycle – for example, an Atari 2600 compatibility module, and the Adam computer.
Video#
The ColecoVision’s video signal is generated by a TMS-9918A Video Display Controller (VDC) chip. It was also used in the TI-99/4, MSX computers and some early Sega game consoles.
The VDC can generate a ×ばつ192 frame at 60 FPS (50 FPS for PAL). There are several video modes, which we’ll describe in more detail later, but here is a brief summary:
Text : 40 columns by 24 rows of text. Each character is 6x8 pixels, and there are only two colors onscreen (foreground and background).
Graphics 1 : 32 columns by 24 rows of text. Each character is 8x8 pixels, and can have separate foreground and background colors.
Graphics 2 : 32 columns by 24 rows, with 768 different character patterns – in other words, enough to cover the entire screen. Each cell has 8 different foreground/background colors, one for each scanline.
Bitmap : Displays a 64x48 color bitmap.
On the ColecoVision, all colors come from a fixed palette of 16 colors.
Index |
Color |
|---|---|
0 |
Transparent |
1 |
Black |
2 |
Medium Green |
3 |
Light Green |
4 |
Dark Blue |
5 |
Light Blue |
6 |
Dark Red |
7 |
Cyan |
8 |
Medium Red |
9 |
Light Red |
10 |
Dark Yellow |
11 |
Light Yellow |
12 |
Dark Green |
13 |
Magenta |
14 |
Gray |
15 |
White |
Most of the graphics modes (except Text) can have sprites overlaid on top of the background. You can have up to 32 moveable 16x16 sprites anywhere on the screen, with the limitation that only 4 sprites may coexist on a single scanline. Each sprite can be assigned its own color from the palette, which is displayed for "on" pixels; all "off" pixels are transparent.
Sound#
Sound is provided by a SN76489 Digital Complex Sound Generator (DCSG) from Texas Instruments. The same chip was also used in several home computers and game consoles, as well as arcade games like Mr. Do!.
It can produce 3 square wave tones simultaneously, each tone generated by a frequency divisor with 1024 possible values. The lack of divisor range means that not many bass notes can be produced; the lowest frequency possible is 109 Hz.
There is also a pseudorandom noise generator, which can either generate noise directly or be used as a frequency divider.
Controllers#
The ColecoVision came with two rectangular controllers with a stubby round joystick and buttons on the side. There is a 12-digit keypad on the controller, into which plastic overlays could be slipped for certain games.
An optional driving controller and a trackball controller were also available via the Expansion Module port.
Memory Map#
A system’s memory map describes which components (sometimes corresponding to physical chips) are connected to a given range of addresses. On many 8-bit systems, there is a single memory map which links the main CPU bus to all other components – e.g. RAM, ROM, and support chips.
The ColecoVision has three distinct memory maps: two are connected to the CPU, and one is behind the Video Display Controller.
On the ColecoVision, the Z80 CPU’s main (address) bus is connected to 1K of RAM, the built-in BIOS ROM, cartridge ROM, and the expansion port:
Start |
End |
Description |
Read/Write? |
|---|---|---|---|
0000ドル |
1ドルFFF |
Built-in BIOS ROM |
read |
2000ドル |
5ドルFFF |
Expansion port |
read/write |
6000ドル |
63ドルFF |
RAM, general-purpose |
read/write |
8000ドル |
$FFFF |
Cartridge ROM |
read |
The Z80’s IN/OUT instructions access the I/O bus. It controls video and sound, and also reads the controller inputs:
Start |
End |
Description |
Read/Write? |
|---|---|---|---|
80ドル |
9ドルF |
Set keypad mode |
write |
$C0 |
$DF |
Video (VDC) registers |
read/write |
$E0 |
$DF |
Set joystick mode |
write |
$E0 |
$FF |
Sound registers |
write |
$E0 |
$FF |
Controllers |
read |
The majority of RAM in the system, 16 KB (4000ドル bytes) is directly connected to the Video Display Controller. It cannot be accessed directly by the CPU, but only via the video I/O ports, one byte at a time.
However, the video RAM memory map is not fixed. The programmer can configure the VDC to use different regions of RAM for different purposes. Each of these regions is called a table, and their locations are configured via registers.
There are five different tables:
Image Table – Defines the background tile map, which selects a character out of the pattern table for each cell on the screen.
Pattern Table – Defines an 8x8 (or 6x8 in Text mode) bitmap for each character.
Color Table – Varies between graphics modes, but generally chooses colors for either characters or regions of the screen.
Sprite Attribute Table – Defines position, bitmap, and color for each of the 32 possible sprites.
Sprite Pattern Table – Defines a 16x16 bitmap for each sprite, with 64 bitmaps in each table. There is also an 8x8 sprite mode with 256 bitmaps.
Tables cannot be placed at arbitrary locations in the 16 KB of video RAM; each table has a specific granularity that limits its possible starting location. For example, the Sprite Pattern Table has a granularity of 800,ドル so it can be set to location 0,ドル 800,ドル 1000,ドル or 1800ドル. In some modes, the granularity is limited further.
Table Name |
Granularity |
Description |
|---|---|---|
Image Table |
|
Background tile map |
Pattern Table |
|
Character bitmaps |
Color Table |
|
Background color map |
Sprite Attribute Table |
|
Sprite positions and attributes |
Sprite Pattern Table |
|
Sprite bitmaps |
Programming#
Almost all ColecoVision commercial titles were written in Z80 assembly language. This allowed developers to fine-tune each and every byte of their programs. This was critical when fitting games into the small but expensive in the game cartridge. It also allowed for clever optimizations which squeeze the most performance possible out of each frame of animation.
Nowadays, homebrew ColecoVision developers usually write games in either assembler or C, the latter using the SDCC compiler toolchain. Writing in C gives you more functionality per line of code. While it has lower performance and greater code size than a well-written assembly program, you can still write a pretty good game in C.
!!! Note: The 8bitworkshop IDE doesn’t use the original ColecoVision BIOS.
Instead, we replace it with a minimal (yet incompatible) open-source BIOS.
Our C library interacts with the hardware directly and doesn’t need to call BIOS routines, so all our version does it look for a cartridge and start it.
Our BIOS also contains a bitmapped font that can be used by cartridges.
If you want to use your own BIOS, upload it to the IDE with the name coleco.rom.
Programming the ColecoVision hardware, especially the VDC, is a little tricky, so we’re going to use an open-source C library called LibCV, and its companion library LibCVU. They relieve some of the drudgery of programming I/O ports directly.
We can include these libraries in our source file with the #include preprocessor directive, like so:
#include"cv.h" #include"cvu.h"
Graphics Functions#
The majority of LibCV deals with graphics. There are functions for turning the screen on and off:
externvoidcv_set_screen_active(boolstatus); externboolcv_get_screen_active(void);
There are functions to change the video mode, and set the background and foreground colors:
voidcv_set_screen_mode(enumcv_screenmodemode); enumcv_screenmodecv_get_screen_mode(void); voidcv_set_colors(enumcv_colorforeground,enumcv_colorbackground);
These functions set the location in video RAM of the five tables:
voidcv_set_image_table(cv_vmemploc); voidcv_set_color_table(cv_vmemploc); voidcv_set_character_pattern_t(cv_vmemploc); voidcv_set_sprite_pattern_table(cv_vmemploc); voidcv_set_sprite_attribute_table(cv_vmemploc);
There are functions to set sprite size, and to get the status of the collision flag (when any two sprites collide) and invalid flag (when there are too many sprites on a scanline):
voidcv_set_sprite_big(boolstatus); boolcv_get_sprite_big(void); voidcv_set_sprite_magnification(boolstatus); boolcv_get_sprite_magnification(void); boolcv_get_sprite_collission(void); boolcv_get_sprite_invalid(uint8_t*sprite);
There are several functions that copy data to or from video RAM. There are "fast" and "slow" versions; the "fast" version can be safely used when the screen is inactive (turned off) or the video signal is in VBLANK. The "fast" version can also be used in Text or Multicolor modes, where the VDP doesn’t work as hard.
// copy to video RAM voidcv_memtovmemcpy_slow(constvoid*src,size_tn); voidcv_memtovmemcpy_fast(constvoid*src,size_tn); // copy from video RAM voidcv_vmemtomemcpy_slow(void*dest,size_tn); voidcv_vmemtomemcpy_fast(void*dest,size_tn); // fill video RAM with bytes voidcv_vmemset_slow(intc,size_tn); voidcv_vmemset_fast(intc,size_tn);
You can also read and write from video RAM byte-by-byte using these functions:
voidcv_set_write_vram_address(cv_vmempaddress); voidcv_set_read_vram_address(cv_vmempaddress); inlinevoidcv_voutb(constuint8_tvalue); inlineuint8_tcv_vinb(void);
Controller Functions#
There are functions to read the keypad and joystick ports, and to set the spinner interrupt handler which changes when a spinner is moved:
structcv_controller_state{ uint8_tkeypad; uint8_tjoystick; }; voidcv_get_controller_state(structcv_controller_state*state,uint_fast8_tcontroller); voidcv_set_spint_handler(void(*handler)(uint_fast8_t,uint_fast8_t));
Sound Functions#
The sound functions are relatively simple; you can set volume (in decibels) and the frequency divider for each of the three square wave channels. You can also set the noise channel:
externvoidcv_set_attenuation(enumcv_soundchannelchannel,uint8_tdezibel); externvoidcv_set_frequency(enumcv_soundchannelchannel,uint16_tfrequency_divider); externvoidcv_set_noise(boolwhite,enumcv_shiftshift);
Interrupt Functions#
The video interrupt handler executes at the end of the video frame, before the VBLANK starts. You can set your own function to execute when this happens:
externvoidcv_set_vint_handler(void(*handler)(void)); externvoid*cv_get_vint_handler(void); unsignedcharcv_get_vint_frequency(void);// returns 50 or 60 Hz
Utility Functions#
Functions to make setting sprite tables easier:
// Write sprite to display memory. Use the location of the sprite table as base. number should be in [0, 31]. voidcvu_set_sprite(constcv_vmempbase,uint_fast8_tnumber,conststructcvu_sprite*sprite); // Set the x coordinate of the sprite's upper left corner. x will be clamped to [-32, 255] voidcvu_set_sprite_x(structcvu_sprite*sprite,intx)__preserves_regs(d,e); intcvu_get_sprite_x(conststructcvu_sprite*sprite)__preserves_regs(b,c,d,e); // Set the y coordinate of the sprite's upper left corner. y will be clamped to [-32, 207] voidcvu_set_sprite_y(structcvu_sprite*sprite,inty)__preserves_regs(d,e); intcvu_get_sprite_y(conststructcvu_sprite*sprite)__preserves_regs(d,e); // Set them both at once. voidcvu_set_sprite_xy(structcvu_sprite*sprite,intx,inty); // Set the sprite's color. voidcvu_set_sprite_color(structcvu_sprite*sprite,enumcv_colorcolor);
If a sprite has a Y-coordinate of 208, that sprite and all sprites following are hidden.