How to change the built-in game in your SEGA Master System BIOS! (Part 1)

In this series you’ll learn how to make a custom SEGA Master System BIOS so that you can change the built-in game and replace it with any game or software you like!

This is going to be a long post, split into two parts.

The whole ordeal started because I wanted to hack a SEGA Master System BIOS (SMS from now onwards) to load the MDFourier analysis tool (ported to SMS from Mega Drive by Pinobatch) for people who don’t own a flashcart and/or don’t want to invest into one.

To put it briefly, I ended up learning Z80 assembly which I had absolutely zero intention to do, but here we are (and it was a fun, albeit frustrating experience).

Let’s start by learning how the Master System BIOS works.
There are two versions which do things differently: the Japanese and the US/EU.

The Japanese Master System BIOS (often referred to as v2.1) makes a check if there’s something connected to the card slot, the cartridge slot or the expansion port (I have no clue about this last one) in that order and if nothing is found, then shows a bumper screen (an animation with information on what to do – ie: insert the damn cart if you want to play the game! Duh!).

The EU/US Master System BIOS are pretty different as they often offer a built-in game.
The v1.3 and v2.0 variants first show a bumper screen, then run the checks and if they don’t find anything, they show you a screen with instructions on what to do.
This screen has a secret game in it you can access by pressing the two buttons + up on your controller.
The other variants with built-in games instead do the same thing but if they can’t find anything connected, they boot the built-in game.

The checks here are completely different, much more involved and take a long time too as they were made to avoid people booting Japanese or unlicensed/pirate games.
You now probably realize why lots of people mod their SMS with the Japanese BIOS: it’s region free, it can boot anything and doesn’t run any real check apart from a very simple one.

Anyway, onto the main topic.

SMS games live in a certain space in the ROM and you can’t move them otherwise they’re gonna break.
The same is true for the BIOS of course so between relocating an entire game everytime (which is unbelievably time consuming) and a small BIOS routine, the second approach is the clear winner.

Let’s start with the EU/US BIOS: we don’t care about the intro/bumper screen. It takes a lot of ROM space and it wastes a lot of time on every boot.
So let’s move forward and see where the checks actually start.
Using a debugger, we can see that the checking code starts at address 0108 and ends at 0128 and it loads a chunk of ROM starting at address 0289 up to 0365 into RAM at address C700 which holds the various checks regarding the presence of the "TMR SEGA" string, region code and checksum.

I’ll leave the disassembly below, but the gist of it is:

  1. Load 0289 to 0365 in RAM
  2. Launch the routines loaded in RAM
  3. Change access from BIOS + RAM to Card slot + RAM
  4. Check for the presence of the "TMR SEGA" string at addresses 1FF0, 3FF0 and 7FF0
  5. If found, proceed to check the region by reading the high byte either at 1FFF, 3FFF or 7FFF: if it is 4 then it’s an export ROM (ie: non-Japanese), and we can go on
  6. Checksum test, which is a headache, but the short of it is it calculates a checksum and compares it to the one found in the ROM. If they match, we can finally boot the damn game otherwise if 5. or 6. failed, show a screen with an error
  7. If nothing is found at 4. then change access to Cartridge slot + RAM and do 4. to 6. Do the same again if nothing is found moving to Expansion slot + RAM.
  8. If nothing is found either in the Card, Cartridge or Expansion slot, change access back to BIOS + RAM and either show the information screen (with the secret game if BIOS is v1.3 or v2.0) or boot the built-in game.

The Japanese BIOS (v2.1) is much simpler and yet I failed to find the routines so, based on the information gathered on the internet on how it works, I bodged a custom BIOS using a mish-mash of the Japanese check routine disassembly found on the SMSPower wiki and the EU/US BIOS *

What I did is I reused most of the code of the v1.3 BIOS and then removed all the check routines and put in the Japanese one that checks if the middle 4 bits of the first 256 bytes are different in the currently selected slot.

If you look at the disassembly above, it’s the same from 0108 to 0128 and the block of code that gets loaded in RAM is the same from 0289 up to 029B where instead I make a call to the Japanese check routine (disassembly below), removed the other two calls which were now useless (and, besides, that code didn’t exist anymore) and the rest is the same up to 02B4.

* Of course I completely failed to realize that in that very same page there was a full commented disassembly of the Japanese v2.1 BIOS. Luckily when I checked at a much later time I discovered it did the exact same things I did! Hooray!

Knowing how the BIOS works, now it’s just a matter of remapping the various calls and pointers.
Luckily the code is not huge so it didn’t take long to find all the various calls and references and move them.

Now that we’ve finally moved the BIOS to the end of the ROM space, we can put in any game or software we like! Here’s how it looks like at the end and at the beginning (Japanese BIOS taken for example):

As you can see, though, there’s an issue.
To explain it, let’s look at the second picture (the start of the ROM).

The first byte is F3 (di – disable interrupts). This is standard and it’s found among all of the games/software.
The 3 bytes after that, C3 90 1F is jp 1F90h which means “jump” to the address 1F90 and, if you look at the first picture, that’s exactly where our BIOS lives!

So the way this works is that the ROM is loaded and it immediately jumps to run the BIOS routines. This way if a cartridge/card/expansion is inserted, it is booted.
But what happens if nothing is found?
The answer is at address 1FB4 where you can see another F3: that’s the start of the actual game!
But why is it there?

Remember the start of the ROM which had that 3 bytes taken by the jump?
Well… that’s 3 bytes we have “stolen” from the game we want to integrate in the BIOS, so we have to put them somewhere else! And that’s where we’re going to put it, along with another jump to go back at the beginning of the ROM where the game actually is!

Does all of it sound confusing? Of course it does, that’s why we’re going to make a practical example with MDFourier.
Let’s take a look at how the MDFourier starts:

Ouch.
As we can see, it starts with F3 (di) which is already there, so all good.
Then we need 3 bytes, but unfortunately the next instruction, ED 56 (im 1), is 2 bytes. That means that we have to move the next instruction as well, which is 31 3C C8 (ld sp,C83Ch).

So let’s cut those…

…and put them in our BIOS right after F3 at address 1FB4!

We’re almost done, now we just need to jump back at the start of the ROM, but at the correct spot!
Looking at the previous image, we can count the bytes that we have moved (just look at the 00) and we have to jump back right at the end of them which, in this case, is 0006.
The jump instruction jp has bytecode C3 which has to be followed by the address byteswapped, so we’ll have to add C3 06 00.

Alright, now the last thing we need to do is to add the jump to the BIOS routine which, as you can see, lives at 1F90, so we’ll have to add C3 90 1F.

And we’re done!

Bear in mind this was done with a 8KB ROM which fits in a 27C64 EPROM, for actual games you’re going to need a bigger BIOS.
You can fit games up to 32KB in a BIOS and, of course, the BIOS will have small changes in addressing as the BIOS won’t live anymore at 1F90, but, for example, in a 32KB BIOS it will be at 7F90 (so you’ll have to adjust the jump address accordingly).

Hope this was more or less clear to all of you.
In the next article we’ll make another practical example with an actual game!

1 thought on “How to change the built-in game in your SEGA Master System BIOS! (Part 1)”

Leave a Comment