Sunday, July 5, 2020
Batty over Bits - The Complexity of the Intellivision's Memory Layout
The Atari 2600 had a rather conventional design by later home computer standards. It's CPU, the 6507, had an 8-bit data bus and a 13-bit addressing bus. Whatever it did, it did in multiples of 8-bits, which has become the accepted standard for computer design. But its' main competitor, the Mattel Intellivision, has a memory architecture remarkably more complex than its older rival as well as many successive home consoles. Even most later 16-bit systems do everything in 8-bit, 16-bit, 24-bit etc. It is important for anyone wanting to get into Intellivision to understand why it is different. In this short blog post, I will try to explain those differences.
The Intellivision runs off the CP1610 CPU, which is one CPU in the CP1600 series. This CPU is a genuine 16-bit CPU, it has a 16-bit external address and data bus and has 16-bit internal registers. It can operate on two bytes at a time which can have a speed advantage over a processor like the 6502 which can operate on only one byte at a time. The CP1610 uses memory-mapped I/O like the 6502.
The CPU communicates with AY-3-8900 Standard Television Interface Circuit (STIC) and the AY-3-8914 Programmable Sound Generator (PSG) over its address and data bus. The STIC has a 14-bit address and data bus and the PSG has an 8-bit data bus and provides two 8-bit I/O ports for the joystick ports. All three chips multiplex address and data lines on the same pins, requiring additional signals to differentiate an address signal from a data signal.
The CPU instructions are where things start to get really interesting, yet rather unusual. CPUs have operational codes (opcode) to tell it to do something such as load a byte into a register, store a byte into memory or perform a logical AND between a two values. In a 6502, each opcode is assigned to a particular 8-bit byte and which may be followed by one or two bytes representing a value or a memory location. Because 6502 opcodes are encoded in 8-bits, the 6502 could theoretically execute 256 different instructions (only 151 are valid). Each 6502 opcode also specifies the memory addressing mode (absolute, immediate, implied, zero page, relative etc.) that the function will perform.
The CP1610 encodes its opcodes using 10-bits, giving it the ability to execute 1024 different instructions. A 10-bit value is called a decle. Actually the CP1600 series can use 16-bits to encode its instructions but the upper 6-bits were reserved for future expansion that never came to be. Not unlike the 6502, the CP1610 opcode will specify the memory addressing mode to be used, but does so in a fashion defined by the bits set in the opcode in a non-arbitrary way. Each address of the CP1610 can access two bytes of data, so the CP1610 can address 128 Kilobytes of memory and I/O.
The CPU has access to a 4096 x 10-bit Executive ROM (ExecROM) which acts as a BIOS. Because this ROM executes opcodes, it must be 10-bit. The Intellivision II adds another 256 x 10-bits to the Executive ROM., intended to break third-party games which do not contain the data that official cartridges contain. There is also 240 bytes of 8-bit scratchpad RAM available to the CPU (It is really 256 bytes but 16 bytes are lost to the PSG's address overlap). All CPU data accesses to the PSG are 8-bit.
The STIC has access to a 2048 byte Graphics ROM (GROM) and 512 bytes of Graphics SRAM. Both are accessed with 8-bits of the STIC's data bus. The ROM contains a font and other fixed graphics patterns which a game can use at any time while the SRAM is intended for game-drawn custom graphics tiles. The STIC uses 14-bit registers whereas the PSG uses 8-bit registers.
Finally, the CPU and the STIC communicate with each other using a shared dual-ported RAM chip. This RAM chip contains 352 x 16-bits or 704 bytes. The CPU communicates with the RAM chip via its 16-bit data bus and the STIC communicates with the RAM chip via its 14-bit data bus. This RAM holds the background tiles to be displayed (20x12 tiles, 159x96 pixel resolution) in the bottom 14-bits of 240 words, the upper 2-bits and the remainder of the RAM can be used by the CPU. (The graphics resolution of the Intellivision is really 159x192 because sprite tiles can have double the vertical resolution of the background tiles.)
Cartridges use 10-bit ROMs, which they must because they contain programming opcodes. The internal ROMs, RAMs, STIC and PSG have an official monopoly over the CPU's memory map from $0000-$3FFF while cartridges can use most areas within the $4000-$FFFF. Cartridges can contain ROM and RAM, but all but three or four commercial titles contained only ROM.
ROM can be mapped almost anywhere where peripherals are not present. The Intellivoice, Intellivision II and ECS add ROM in certain spots of the memory map which cuts down on areas available for cartridge ROM. The STIC registers have some mirrors in the cartridge area as well, so ROM cannot overlap with those. Generally speaking, it is always safe to map ROM to : $4800-$6FFF, $9000-$BFFF, $D000-$DFFF, $F000-$FFFF. RAM was much more constrained in where it could be put in the memory map because it has to be written to as well as read, and the few games that came with RAM only came with 1KiB or 2KiB of it and it was always 8-bit.
There are two "keys" to understanding Intellivision ROMs. The first is that each cartridge is wired to assert various memory address ranges available on the bus. The Commodore VIC-20 uses a similar system. A binary dump of the ROM chip does not tell you which memory ranges the ROM expects to use. Emulators can use a hash check and a database to determine how a game runs, but they fail when a ROM is altered or a new ROM is discovered. Some emulators have separate configuration text files which tell the emulator what memory ranges to map the various areas of the ROM. There are ten configurations which commercial games used during the Intellivision's lifetime, homebrew may add more. Finally, there are multiple header formats for Intellivision ROMs which do the same thing appended to the ROM itself.
The second thing to understand about ROMs is that "bytes" are 10-bits for the commercial games released during the Intellivision's lifetime. Homebrew ROMs may use the full 16-bits, there is no hardware reason why the Intellivison cannot address full 16-bit ROMs.
If you open an Intellivision ROM in a hex editor, you will see complete columns where the hex value is always 00, 01, 02 or 03 and the next and previous column is often not one of those values. That arrangement often signifies the way data is represented in an Intellivision ROM. The highest value you can designate with 10-bits is $03FF or 1023 decimal and opcodes are designated with 10-bit values and operate on 8-bit or 16-bit data values. Additionally, any ASCII text will have a space between each letter. Essentially you must treat an Intellivision ROM as a 16-bit ROM where a pair of bytes usually will not go above $03FF. Because you cannot store 10-bits in an 8-bit byte, it is stored in two bytes/16-bits (sometimes called a word). The "two high bits" of each decle should be stored in the "Little Endian" format where the low 8-bits comes before the high 2-bits. The CP1610 sees data as Little Endian. Some ROM dumps use a Big Endian format. No-intro and GoodINTV supplies Intellivision ROMs as pure binaries in the Big Endian format.
When it comes to ROM sizes, the size of the ROM as it appears as stored on your computer can be deceiving. Astrosmash, one of the earlier but one of the most popular games, has a binary ROM size of 8,192 bytes when stored on a PC. However, that is when the game is viewed through a 16-bit lens. Astrosmash is actually 4,096 decles in size, the equivalent to 5,120 8-bit bytes. Later games can be 8,192, 12,288, 16,384, and 24,576 decles. In the binary ROM format their size will be double the decle size. Remember than in an Intellivision, the CPU permits each address location to hold up to 16-bits of data, although when we speak of Cartridge ROMs, each address location holds 10-bits of data. Although commercial games released during the Intellivision's lifetime used 10-bit Mask ROMs, some homebrew may use 16-bit EPROMs, which is easier to program and put on a cartridge today than a 10-bit ROM.
"Although commercial games released during the Intellivision's lifetime, some homebrew may use 16-bit EPROMs" <-- I feel there's something missing just before the comma, but I'm too uninformed to know exactly what. Did the old games use 10-bit EPROMs?
ReplyDeleteFixed that, thanks for pointing that out!
Delete