Konami made some of the best games for the MSX computer platform.
Unfortunately, the market being what it is, those cartridges have
become expensive collectibles rather than cheap games, which takes all
the fun out of it. Before we can build a bootleg cart, we need to
understand Konami’s unique mapper.
My goal for this project was to make a functional cartridge that could
play Konami’s Knightmare II: The Maze of Galious. Although I think the
game is interesting and ambitious, this was mostly because blog friend
famiclone loved the game, and I owed him an MSX in exchange for the
lovely ColecoVision and busted 48k Spectrum he sent me.
Failure to Launch
For a couple years now, I’ve wanted to play [1]The Maze of Galious on
an MSX. Galious is a side-scrolling action-adventure game with some
long gameplay, multiple characters, and some fiendish puzzles. Blog
friend famiclone has been really interested in it, and I wanted to see
what all the fuss is about, too.
At first, I looked at the used market to see if I could buy a
cartridge. The absolute lowest I’ve seen a (very worn) cartridge listed
for over the years is ¥4800. In retrospect, after all this adventure,
that doesn’t seem like much, but “spending fifty bucks instead of
learning something” is not the name of this blog.
As you have probably inferred, the obstacle was understanding the
mapping scheme in use. I’d soldered together a bunch of homebrew MSX
cartridges before, but they were always a simple “bare ROM” on a
pre-made board that is keyed off of slot-select. No fancy mappers, and
limited to 64k at most. I certainly did not program the software on
those cartridges – MSX programming is an experience I am saving for the
future!
I set about trying to figure out the paging scheme in use, by piecing
together MSX.org wikis and squinting at pictures of other mega-ROM
boards. But everything was very confusing, and it seemed like with
every step forward, I’d end up having to pull the design apart and redo
it from scratch, or end up with way too many parts.
So what changed? I got talking to [2]bsittler, a huge MSX fan, about
the MSX.
When he heard about the project, blog friend bsittler sent me [3]some
Konami-style cases from Retro Game Restore that he had lying around the
property. This act of generosity was the spark that motivated me to
actually finish this project up enough to send it to fab. Thank you!
The version-one PCB as it was sent to JLCPCB. It reads "Oyanami Megabit
Mapper for Legitimate Purposes."
I made Microchip send me a sample DIP32 SST39SF040 EEPROM, which was
very nice of them to provide. Thank you, too, Microchip!
For my initial run I decided to try Galious. I could also have done
Metal Gear, but I only wanted to have MSX1 games on this initial cart.
Mapping for These Territories
What is a cartridge mapper, and why do we need one?
A lot of early MSX games are similar to most ColecoVision cartridges: a
bare ROM on a PCB, without any fancy logic.
As cartridges got bigger, they no longer fit entirely into the Z80
CPU’s 64k of address space. Some page-switching had to be added. It’s
just what it sounds like: instead of looking at a whole book’s worth of
information laid out on a table all at once, we cut that information
into pages, and then flip the book to look at one page at a time.
In other words, one address in the Z80 space could now point to
multiple different addresses on the ROM. This was an inevitable
development: anyone who knows programmers can tell you that they always
need more memory (both ROM and RAM!)
Long-time readers will remember that we’ve delved into cartridge
page-switching routines before, such as [4]the explanation of how UNROM
cartridges worked on the NES.
Page switching was built into the MSX standard’s design from the start.
ASCII Corporation, which originated the standard, had a whole lot of
programmers on staff and they got what they wanted. MSX’s basic “slot”
scheme makes it easy to access two 64k cartridges while still keeping
BIOS ROM and RAM available.
MSX Slot Mapping
Because the MSX came relatively late in 1983, the design of the
standard benefited from seeing the limitations of other Z80-based
systems. Many parts were inspired by my beloved NEC PC-6001, but ASCII
picked and chose some reasonably sane choices. For our purposes at the
moment, one of the more significant features of the MSX design is the
slot system, which allows manufacturers to specify a huge memory map
that can be “paged” in and out at runtime.
I had tried to fit the slot system into my head on many previous
occasions. It is hard to go into any discussion of the MSX hardware
standard without seeing words like “slot,” “mapper,” “page,” and
“segment” thrown around, often interchangeably. Things made more sense
once I talked to bsittler, who has had a long history tinkering with
the MSX and features a near-infinite amount of patience for my dumb
questions.
Here, then, are the basic rules as I understand them:
1. The MSX divides the 64kB Z80 address space into four 16kB “pages.”
2. Each page can choose between one of four “slots” to point to, which
usually (but not always) correspond to “built in,” “cartridge slot
1,” “cartridge slot 2,” and “miscellaneous.”
3. To set the pages, you write a byte to I/O port $a8 to tell it what
slot to display at which page^[5]1. Page 3 ($c0000 to $ffff ) is
the most significant half-nibble of that byte.
I wrote a quick example, based on [6]my 16kB Sony HB-101, that you can
play with on your own to see what I mean:
Click on slots on the left-side table in order to map them into the
MSX's Z80 address space on the right.
Assign MSX Slots
Slot 0 Slot 1 Slot 2 Slot 3
Page $C000 - $FFFF 16k RAM Cart Slot 1 Cart Slot 2 Nothing
Page $8000 - $BFFF Nothing Cart Slot 1 Cart Slot 2 Nothing
Page $4000 - $7FFF Main ROM (top) Cart Slot 1 Cart Slot 2 Hit-Bit
Organizer
Page $0000 - $3FFF Main ROM (bottom) Cart Slot 1 Cart Slot 2 Nothing
Current Memory Map
Page Mapped to...
Page $C000 - $FFFF ...
Page $8000 - $BFFF ...
Page $4000 - $7FFF ...
Page $0000 - $3FFF ...
Slot-Changing Instructions
The critical point I didn’t get on previous attempts was that each page
can only use slots in its row. For example, on this example of the Sony
HB-101, you can’t map the main ROM into high memory. I had been
confused before why everything seemed to still be in the same order,
despite there seemingly being a lot of flexibility in the design of an
MSX-standard computer.
If you put the above example into the configuration where RAM, the BIOS
ROM, and the cartridge are all assigned into the memory map at the same
time (i.e. OUT ($a8), 0b00010100), you’ll find that the lowest address
available to the cartridge is $4000 . This is why MSX ROM cartridges
decode their initialization code at $4000 . It’s where the MSX BIOS
will look for it when it mounts the slot.
There is a [7]“slot-expander” peripheral to further subdivide these
slots if you need more space. The MSX2 has a lot of additional fancy
mapper schemes built into the standard as well, but I don’t understand
those yet, so we’re not going to cover those in this article.
Under the standard MSX scheme, a cartridge is split into four 16k
slots, which means that your theoretical game can be a whopping 64
kilobytes without requiring any additional fancy mapping schemes, which
add cost to every cartridge. That’s a huge amount of space, if you’re
used to the Nintendo NROM, which limited cartridges to a measly 16k of
program space.
Konami Bon Ami
Unfortunately for the MSX planners, games kept getting bigger and
bigger… When Konami started making 128-kilobyte games, they had to
implement an extra mapping scheme of their own.
That’s where the “MegaROM” mapper comes in: it lets you page-switch one
megabit (128 kilo bytes) of cartridge ROM so that it can be fully
accessed by the MSX through the 64k of slots that it makes available to
the cartridge.
The MegaROM mapper design. The four 16k slots of the cartridge are
expanded to point to arbitrary 16k segments in a ROM.
Under the Konami scheme, we divide the 1Mbit ROM into eight 16k
segments.
Each 16k slot of the MSX cartridge’s slot space can now choose to point
to one of eight 16k segments of the ROM on the cartridge. This design
is very similar to that of the MSX’s own mapper!
There is just one caveat: on the early Konami mappers, the $4000 to
$7fff slot is always mapped to the first segment of the ROM. This is
because the MSX will look at this slot first in order to boot a
cartridge, so it has to contain the boot code for the game when the MSX
turns on.
Why is this fixed, then? Why not make it configurable and just default
to segment zero? It’s probably because Konami would otherwise have to
add logic to detect when the MSX is starting up, and reset all these
registers to zero^[8]2. I’m glad they didn’t do this, because it would
have made it much harder for me to implement, but more on that in a
bit.
The Guts of Page Switching
Now that we know logically how things are supposed to work from the
software side of the MSX, how do we actually implement a mapper in
hardware?
At the most basic level, a page-switching scheme controls the upper
address bits of the RAM or ROM that we want to switch. For instance,
you can think of a 32k RAM chip as being four chunks of 8k, arranged in
a line.
A 32k RAM chip split into four 8k chunks.
Instead of being driven directly by the CPU, we instead drive those
lines from some sort of latch. When we want to look at a different
chunk of the RAM, we change the latch’s settings, and it changes how
it’s driving the mapped RAM/ROM’s address lines.
The Konami mapper needs a pretty fancy latch, but it’s still a part we
can just get off the shelf. Let’s ditch the generalities and get down
to how it specifically works..
The Magic 74LS670
Most of the homebrew MegaROM cartridges are based around the 74LS670.
That part is called a “4x4 register file,” which is a very Texas
Instruments name for what is basically four 4-bit latches stuck
together in one teeny tiny chip.
To use the ‘670, you set two address pins (2^2 = 4 registers) and then
can enable read or write. Enabling write sets the registers inside the
chip for the given address, and enabling read expresses the content of
that register on the output pins.
It’s a pretty useful part, especially when you realize that you can
write to a different register than you’re reading from at the same
time. You can almost think of it as a crude, very small dual-port SRAM.
Unfortunately, it’s a little harder to get these days: Digi-Key is
asking over $11 for it in HCT DIP, and most varieties are simply
discontinued. My supplies all came from salvage. I think it could be a
cool project to try and build one of these using a PLD.
The Struggle
I had tried making one of these before, because I figured it was
something simple like the UNROM mapper. Previously, I had started
figuring it out from [9]the MSX.org description of the mapper’s
addresses, but I kept making very complex decode circuits.
This time around, I looked at [10]this thread complaining about a
non-working MegaROM schematic and decided to take a peek. I was
surprised to find that they didn’t route A[14] at all, and started to
puzzle that out on paper.
Eventually, I figured out that A14 doesn’t usefully distinguish any
access. Here, let me show you:
Address Segment A13 A14 A15
$4000 Always 0 0 1 0
$6000 Variable 1 1 0
$8000 Variable 0 0 1
$a000 Variable 1 0 1
As you can see from the table, A[14] isn’t needed to decide between
“paged” and “unpaged” access.
If A13 or A15 are high, then we know it’s trying to read a paged
segment, and we should activate the 74LS670 to set the upper address
lines to whatever it has set.
Otherwise, the ‘670 doesn’t turn on, and the upper address lines on the
ROM would be left low (more on this in a second.) A[14] is just not
necessary to know. Once I figured this out, the penny dropped on the
decoding.
Although it’s not my design, I figure it’s okay to crib from other
designs as long as I’m actually learning from them.
Now that I know how it works, it would be easy to expand to a “Konami
16” mapper (for 256k games) or even something more complicated.
Arrival
In order to rough out the PCB dimensions, I measured a Gerber of
another MSX cartridge using the KiCad Gerber viewer. However, I got the
hole diameter slightly wrong for the case: I measured 4mm, but the
cases provided were 4.5-ish mm when they arrived.
Even so, the edge connector was correct and fit properly into the
system, so we can still test it!
The initial PCB is installed into the black HB-101.
For testing, I grabbed the closest MSX to hand: a black Sony HB-101
that I knew to have exceptionally dirty and glitchy cartridge slots.
Perfect!
Unfortunately, the HB-101 didn’t want to boot my new cartridge, even
after repeatedly cleaning those slots. Instead, the BIOS would just
jump to the built-in Sony HitBit organizer menu every time, indicating
it couldn’t read the cart, or just didn’t like what was going on there.
I decided that I would grab my copy of Tiny Slot Checker and see if
anything legible was coming back from the cart.
Tiny Slot Checked
[11]Tiny Slot Checker is a fantastic MSX utility written by Tiny Yarou,
a Japanese hobbyist. Basically, it scans the MSX’s memory space and
displays what it thinks is installed in each of the MSX’s slots.
Critically, for our purposes, it includes a hex viewer. My plan was to
use this hex viewer to inspect the cartridge slot containing my
prototype Oyanami. That way, I’d be able to see if the cartridge is
able to be read at all. And if the paging scheme was wrong, I’d maybe
even be able to figure out what segment of the ROM it was looking at
instead of the one containing the boot code.
Tiny Slot Checker reported that slot 2 was populated. It tries to make
an educated guess about the contents of the slot, and can fingerprint
many games and BIOS ROMs. In this case, it had no idea what was in that
slot, so it just displayed ?.
Page 0 Page 1 Page 2 Page 3
Slot 0 Main (BIOS) Main Empty Empty
Slot 1 (Tiny Slot Checker) Empty This Tool Empty Empty
Slot 2 (our cart) Empty ? ? Empty
Slot 3 Empty HitBit Tools Empty RAM
Every MSX cartridge must start with ASCII "AB" ($41 $42 ) in order to
be identified by the BIOS as a bootable ROM. We also know that this
magic string must be mounted at $4000 on the cartridge, because that’s
where the MSX looks to boot a cart.
I inspected Page 1, Slot 2 of the cartridge with Tiny Slot Checker’s
hex viewer. Instead of AB, I saw $C1 $84 $21 $C1 !
I went back to my modern computer, and plugged that string into the
search function in [12]my favourite hex editor, Hex Fiend. The only
place in the entire 4Mbit ROM where that byte string could be found was
at the address $72000 , which means that when we accessed the ROM on
the cart, A[13], A[16], A[17], and A[18] are all stuck high.
Don’t be a DIP
For starters, that meant that my DIP-switch for choosing games also
wasn’t working, because it’s the only thing that controls A[17] and
A[18] on the ROM.
Oh, did I forget to mention that DIP switch earlier? I added it when I
realized that it was the same price to get a 4-megabit SST39SF040 as it
is a 1-megabit SST39SF010. This way, I could put four Konami MegaROM
games on the same cart, which I think everyone agrees is more.
The DIP switch is its own kind of mapper, in that it controls the A[17]
and A[18] lines of the ROM, splitting the 4Mbit ROM into four equal
1Mbit chunks (remember again that 2^2 = 4.) It’s just that it’s
actuated with my greasy human fingers instead of an efficient, perfect
machine.
When the ROM switch is closed, it will short A17 and A18 low, defeating
two 10k pullups. Unfortunately, it's only closed when it's "on," which
is the opposite of what you'd expect.
Once I checked my schematic, I realized I had wired the switch up
backward. When the ROM switch is closed, it will short A17 and A18 low,
defeating two 10k pullups. Unfortunately, it’s only closed when it’s
“on,” which is the opposite of what you’d expect.
So that’s one bug found. I turned off the computer and flipped both
DIP-switches to “ON.” If my theory was correct, I should now only see
A[13] and A[16] high in page 1, or $12000 .
That’s not what I got. The byte string $5b , $68 , $67 , $61 was found
at $1e000 – which sets A[13], A[14], A[15] and A[16]. Where did A[14]
and A[15] come from all of a sudden? Page 2 was decoding to the segment
at $18000 , which shouldn’t be possible, because it’s supposed to be a
fixed mapping to $00000 !
Wild Pointers Could Not Drag Me Away From Boot
Momentarily devoid of higher-order thought, I decided to power cycle
the system and see if the pages moved around. If it was randomly
changing, I could assume something was uninitialized or being driven by
a floating pin. After letting the machine sit for awhile, I turned it
back on to find that the same pages were shown in the same spots. What
was going on, I asked the heavens, but they refused to bestow me with
any better insights.
With my sanity returning, I decided to look at pictures of other
MegaROM cartridges. I found a picture of a MegaFlashROM PCB, which
stirred some memories. Surprising myself, I found a 512K Konami
MegaFlashROM cartridge PCB that I had forgotten about in my MSX
cartridges box. Whoops. I could’ve just built this in the first place.
With more luck, I immediately noticed that the 512K FlashMegaROM has a
pretty prominent resistor network. Through the magic of datasheets and
the continuity test, I determined that the FlashMegaROM cartridge is in
fact pulling the segmented lines (all the high address outputs from the
‘670s) low!
It was only now that I remembered the datasheet for the ‘670 said it
was tri-state: it can output true, false, or nothing at all. If I don’t
select the ‘670, it doesn’t drive the output lines at all, leaving the
ROM’s input address lines floating, and picking up whatever cosmic
radio-frequency strangeness that also tells my cat what to do.
In other words, all the segmented address lines on my ROM were floating
whenever I did an access to the “fixed” segment. You know, the segment
that contains the boot code for the cart. By adding the pull-downs,
those address lines are driven low by default, which keeps things
consistent.
Normally, I would expect floating address pins to be completely random,
but this was very consistent. My best guess is that, because Tiny Slot
Checker is reading the ROM sequentially, quick enough to prevent decay
of any internally latched matrix addresses, and always in the same
order, there is some aspect of the ROM’s internal addressing logic that
makes this fairly deterministic (if still useless.) If you have a
better theory, please let me know.
I bodged a 10k onto the paged-A13 output of the 670, and suddenly I was
now reading from $1c000 – A[14], A[15], and A[16] high, but not A[13].
Progress!
Okay, let’s bodge ‘em all.
Four bodged 10k resistors are going from the various paged address pins
to ground. You can also see my sharpie mark indicating that the
mounting hole is too dang small.
After some creative routing of 10ks to avoid shorts, I had wired up all
four of the paged address pins. I turned on the system to see what Tiny
Slot Checker would make of it, but I was surprised to see… a Konami
logo^[13]3!
The title screen for Salamander
The MSX was booting into Salamander!
The logo for Maze of Galious
And with a quick adjustment of the DIP-switches, Galious!
Finishing Touches
There’s one thing missing, as long as you ignore the fact that the PCB
doesn’t work properly out of the box: a cartridge label. Form over
function, that’s what I always say.
I decided to try and get a custom sticker made, and I went to a
Canadian manufacturer, [14]Sticker Beaver. I’ve been meaning to use
this shop for something for quite some time now, and I figure this was
as good as a time as any.
The sparkly Oyanami stickers arrived in a package with a Sticker Beaver
promo brochure and some samples.
After a lot of learning curve in Inkscape, and a little bit of
back-and-forth with the proofs, I had these [15]holographic glitter
stickers cut and sent to me. Even on the free shipping plan, it only
took about three business days to arrive, but it was like waiting for
Christmas morning.
The sticker is applied to the Oyanami cartridge shell. It looks sparkly
and beautiful.
While I was waiting for the stickers, I had time to debug the board.
Now that I knew what was wrong, I made some tweaks to the cartridge
PCB. I added a resistor network to provide the pull-downs (rolling the
DIP-switch resistors into it in the process,) and fixed the mounting
holes. Then I reordered it from JLCPCB, this time choosing ENIG gold
plating.
These new Oyanami Gold cartridges cost more money to make because of
the ENIG, but I think we can all agree that they look pretty cool. And
now they fit in the case!
The gold version-2 cartridge stuck into a case.
That is, as long as you don’t want to socket your ROMs; there’s not
quite enough height, a common complaint about MSX cartridges. This one
is soldered down.
Maze of Galious
Ah, the part of the project where I get to play a game for five
minutes! I did a quick check to make sure the game was bootable, then
spent thirty minutes digging out my AV capture/splitter rig and its
hydra of cables and messing with OBS to record a short clip.
Although Galious involves a lot of keyboard action (for instance, F1 to
open the sub-screen menu,) all the movement, combat, and tricky
platforming is easier with a d-pad. That’s where [16]the FM2AND6 comes
in:
A white game controller, reading "FM2AND6," is sitting on top of the
stark black National CF2700 MSX.
Made by blog friend OMPeaRetro, the FM2AND6 is a familiar controller
layout that’s got a new PCB inside. It offers a no-brainer setup for
2-button games on old Japanese PCs, including the MSX, and 6-button
games on the FM Towns. You’ll hear more about it later, but for now
it’s going to help Popolon and Aphrodite dole out the harshness.
IFRAME:
[17]
https://www.youtube.com/embed/ht72N8Vc1zE?si=QmGodM6B0Zixy4KM
Conclusion
The finished cartridge is inserted into the HB-101, and a sparkly
reflection can be seen on the gloss black of the case.
This was a fun project to do! It all came together fairly quickly,
thanks to the help of some smart friends. And playing these old Konami
games is a lot of fun.
You can download [18]the cartridge KiCad files for yourself from the
GitHub repository. There’s also a bunch of [19]Gerbers on the release
page, which can be sent directly to fabrication.
Now if only I could reflash this cart on the fly… and load games from a
host PC… and… and… and…
References
1.
https://en.wikipedia.org/wiki/The_Maze_of_Galious
2.
https://www.msx.org/users/bsittler
3.
https://retrogamerestore.com/store/msx_cart_shell/
4.
https://www.leadedsolder.com/2020/07/28/portopia-repro.html
5. file:///tmp/lynxXXXXHti2mB/L3475491-4394TMP.html#fn:bios-not-port
6.
https://www.leadedsolder.com/tag/hb101
7.
https://www.msx.org/wiki/Category:Slot_Expanders
8. file:///tmp/lynxXXXXHti2mB/L3475491-4394TMP.html#fn:other-mappers
9.
https://www.msx.org/wiki/MegaROM_Mappers#Konami_MegaROMs_without_SCC
10.
https://www.msx.org/forum/msx-talk/hardware/konami-mapper-circuit-diagram
11.
http://www.tiny-yarou.com/slotchecker.html
12.
https://hexfiend.com/
13. file:///tmp/lynxXXXXHti2mB/L3475491-4394TMP.html#fn:tsc-boot
14.
https://stickerbeaver.ca/
15.
https://stickerbeaver.ca/stickers/glitter-stickers/
16.
https://ompearetro.com/shop/ols/products/fm2and6-custom-controller-for-fm-towns-and-other-japanese-pcs
17.
https://www.youtube.com/embed/ht72N8Vc1zE?si=QmGodM6B0Zixy4KM
18.
https://github.com/barbeque/oyanami-msx-megarom
19.
https://github.com/barbeque/oyanami-msx-megarom/releases