Rygar — Memory Map

arcade Nov 10, 2020

Arcade machines typically divide their memory address space up into multiple segments. A Z80 CPU has a 16-bit address space, which means it can reference 65,536 different memory locations. These different locations may actually point to one or more devices. This is known as memory mapping.

For example, the memory range $0000-$bfff might be mapped to a ROM chip that stores the instructions for the main CPU. A segment from $c000-$cfff might be used by the CPU for temporary storage — called work RAM — for calculations, and store this data in a RAM chip.

A diagram that illustrates the different parts of the address space is known as a memory map.

The memory map for Rygar looks something like this:

$0000-$7fff PROGRAM ROM
$8000-$bfff PROGRAM ROM 2
$c000-$cfff WORK RAM
$d000-$d7ff CHARACTER RAM
$d800-$dbff FOREGROUND RAM
$dc00-$dfff BACKGROUND RAM
$e000-$e7ff SPRITE RAM
$e800-$efff PALETTE RAM
$f000-$f7ff PROGRAM ROM 3 (BANK SWITCHED)

Here you can see that the full address space ($0000-$ffff) is split into segments that are mapped to different devices.

How Do You Make a Memory Map?

Unfortunately, the memory map for every arcade game isn’t readily available. The only way to figure out the memory map is to study the schematic, and figure out which RAM/ROM chips are connected to the various lines of the address bus. It is even more difficult if you don’t have access to a schematic diagram for the arcade PCB.

For Rygar, I ended up printing out the schematic and tracing out the lines of the address bus with coloured pens. I also had to decipher some of the logic circuits involved in enabling various chips for particular address ranges. Obviously, you can cheat and read the source code for another emulator (e.g. MAME), but where is the fun in that?

Also, if you uses someone else's work then be aware they may have skipped parts of the memory map, or interpreted the schematic incorrectly. So it pays to be able to figure this stuff out for yourself.

Tricks of the Trade

Because of the limitations of the Z80 CPU, the Rygar engineers had to do some clever engineering to fit everything within the 16-bit address space.

One trick they used was bank switching. Instead of making all of the read-only memory directly addressable by the CPU, they limited one of the ROMs to a small segment of the address space — just 2,048 bytes from $f000 to $f7ff.

In order for the CPU to access the rest of the ROM data, it must switch between different banks. This is done by writing a byte to a register at $f808, which selects between one of sixteen banks. When the bank register is set, the current bank of ROM data mapped to $f000-$f7ff is changed.

Think of a bank like a small window that the CPU can look through to see the ROM. The CPU can never see the whole ROM at once, but it can slide the window backwards and forwards to see different parts of the ROM when it needs to.

Another neat idea they used was to have part of the address space point to different things, depending on whether the CPU is reading or writing to a particular address. For example, if the CPU reads the register at $f800, then it will get the current state of the player one joystick. But if the CPU instead writes a byte to the exact same register, then it will set the x-axis scroll offset of the foreground tilemap layer.

Doubling up on addresses like this wasn't just a clever thing to do, it is actually quite practical. Sometimes reading or writing to a certain address just doesn't make sense.

As we saw, reading a byte at $f800 represents the value of the player one joystick (i.e. real electrical switches in the real world). But writing a byte to that location doesn't change whether player one is physically moving the joystick or not. It makes perfect sense for a write at that location to do something else instead.

All this means that a memory map might include different mappings, depending on whether you are reading or writing to an address. For example:

Read:

$f800 PLAYER 1 JOYSTICK
$f801 PLAYER 1 BUTTONS
$f802 PLAYER 2 JOYSTICK
$f803 PLAYER 2 BUTTONS
$f804 N/A
$f805 N/A
$f806-$f807 DIP SWITCH A
$f808-$f809 DIP SWITCH B

Write:

$f800-$f802 FOREGROUND SCROLL
$f803-$f805 BACKGROUND SCROLL
$f806 SOUND LATCH
$f807 FLIP SCREEN
$f808 BANK SWITCH

If you are interested, have a look at the Techmo driver in the MAME source code to see a better example of the Rygar memory map. Obviously it contains MAME specific code, but you can still clearly see the memory map and the devices connected to different memory segments.

Tags

Josh Bassett

Hello. I'm a software developer living in Byron Bay, Australia.