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