Author Topic: A Game Boy game that emulates a more advanced CPU  (Read 471 times)

Offline Crow!

  • Newbie
  • *
  • Posts: 29
A Game Boy game that emulates a more advanced CPU
« on: February 05, 2019, 07:20:12 PM »
One of the things I've been doing for the past couple years is making randomizing ROM hacks for old RPGs.  Recently, I started working on Final Fantasy Legend III, a late Game Boy game.  The Game Boy's processor is somewhere between a 8080 and a Z80, but apparently the programmers on the team (who were evidently WAY better at their jobs than the guys who worked on FFIV, let me tell you) didn't much care to program in that environment.  So, they programmed a 24-bit virtual machine, and wrote their game in code that targets that better "CPU" instead.

"Opcodes" for this "machine" reserve 3 bits to describe what sort of argument it will be provided, with options like "16-bit literal" and "8-bit indirect direct page." For opcodes that require an input number, subsequent commands come from a different set of infix operators, including stuff like "multiply" (not in the actual CPU's instruction set, btw) and "bitwise AND". The program also allows subroutine calls, and maintains a stack to facilitate returning to the caller.

In the end, when I changed the rules of the game in FFL3 Lunacy, I actually didn't code a single thing that could run on the Game Boy's processor.  I still did the usual code injection, find unused RAM to work with, etc. shenanigans that I've done with other ASM projects, but I had the privilege to target this more interesting and convenient virtual machine since that was what the game was actually running.
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 2138
    • LairWorks Entertainment
Re: A Game Boy game that emulates a more advanced CPU
« Reply #1 on: February 05, 2019, 11:40:36 PM »
*citation needed

I'm somewhat skeptical that a GameBoy has the power to run a virtual machine of a 24-bit processor on an 8-bit architecture and still be performant in any sort of way. Even with ingenious coding techniques that seems like a virtual (get it?? eh eh? :D ) impossibility.

On the same token I've seen some really impressive things done by programmers that are far smarter than I am so I'm skeptical but not incredulous.

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4688
Re: A Game Boy game that emulates a more advanced CPU
« Reply #2 on: February 06, 2019, 02:07:10 AM »
Lol, Leeor the skeptic.

My first thought was they wanted to re-use existing code that was designed for a different architecture. Rather than re-write, just run it under an emulator.

Though I do get what you're saying Leeor. The Game Boy isn't exactly very high powered, and virtual machines can add a lot of overhead.

@Crow!, I'd be curious if you'd post any details on what exactly you're working on. Is there any sample code you could share? Maybe a screenshot of what you're doing?


Edit: Had to add a link to this:
XKCD #285: Wikipedian Protester
 :P
« Last Edit: February 06, 2019, 02:09:23 AM by Hooman »

Offline Crow!

  • Newbie
  • *
  • Posts: 29
Re: A Game Boy game that emulates a more advanced CPU
« Reply #3 on: February 06, 2019, 03:06:38 PM »
The syntax for the script targeting the 24-bit interpreter works as follows:

First, an operator is supplied with a byte in the format aaabbbbb. bbbbb is the command to be executed.  Commands that cause math to occur look at aaa to decide what sort of argument will follow the command.  Other commands are things like "jump to subroutine" which always takes a 16 bit argument, or "return from subroutine", which doesn't take any argument.

The "return from subroutine" command 06 causes the game to pop an item from a stack of 16-bit addresses whose contents build up from address cc11, with the address of the top of the stack being tracked in cc0f-cc10.

When entering a command which does math, commands change meaning until "end of current expression" 1f is found.  This second set of commands (which I've been calling operators) also follow a aaabbbbb format, with aaa having the same meaning as it does in the previous set of commands.

Within an expression, the game uses addresses cc05-cc07 as a 24-bit accumulator, while cc08-cc0a are in charge of receiving data from the argument.  The interpreter will separate the data type from the operator's id, call a subroutine to grab the argument based on the data type, then call a subroutine to perform the operation requested with the two numbers now loaded.

The data types (aaa part of the commands listed above) appear to be as follows:
Quote
00 XX: Direct page.  Points to c9XX as an 8 bit number.
20 XX: Direct page. Points to c9XX as a 16 bit number.
60 XX: Indirect page.  Points to the data that the 16 bit address stored in c9XX itself points to.
c0 XX: Literal.  Loads the number XX from the script.
e0 XX YY: Literal.  Loads the number YYXX from the script as a 16 bit number.

Here are data types I haven't seen in action but that I suspect exist:
40 XX: Indirect page.  Points to the data in the direct page that the 8 bit address stored in c9XX points to.
80, a0: should exist, but I have no knowledge of what they do.  Maybe for 24 bit data?  The virtual machine is set up to handle that but the code I've touched hasn't needed it.

Command 03, which is "call a GB-native code subroutine" is used sparingly.  It's implementation is pretty cool, though - since the game boy's only CALL opcodes can only take a literal, but the game wants to use to the routine specified by the script, the game instead pushes the intended return address to the stack then jumps using JP (HL).


Here's an example of code I've written:
Code: [Select]
20 47 		target c947 as a 16-bit number.  This RAM seems to be unused.
ec 80 dc load the number dc80 - this is the address of a timer for animation; it cycles from 0 to f constantly.  I'm going to use it like an RNG, which is probably OK because its current state depends on the exact frame when the player cleared the last text box.
1f save it
00 95 target c995 as a 8-bit number
6c 47 load the thing pointed to by c947.  Notice I had to first point at the data and then use it; if there is a "load data from the following 16-bit address" data type, I haven't seen it.
c5 03 and with 03
1f save
05 YY YY call my "make sure robots have stuff" subroutine
05 cf 5d call subroutine 5dcf (does all the heavy lifting; I'm going to run out of space in this section of the ROM soon so continue code over there.)
02 e7 58 jump to 58e7 (i.e. continue on with the game's usual script here)

Inside subroutine 5dcf, here's a conditional where I use my "random" number:
61 47 Begin a conditional, with the left hand side of that conditional contained in the address c947 itself points to.
cf 02 0f seems to be the "<=" operator; a subtraction is performed immediately, and the game marks that 0f was the most recently used comparer in cc03.  cf, then, is "compare with the number provided here".
1f Evaluate the expression.  If it was true, do the next command.  Otherwise, skip that command.
02 78 3f Jump to 3f78, where I handle turning the character into a robot.

The way this system handles data is the main reason I call it a virtual machine rather than a script engine - it has a direct page, it allows indirect indexing, etc, making coding for it feel far more like ASM than like BASIC or whatever.  It maintains a stack pointer and an execution pointer, but doesn't seem to have the additional indexing registers processors generally do.
« Last Edit: February 06, 2019, 03:10:03 PM by Crow! »
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline lordpalandus

  • Hero Member
  • *****
  • Posts: 733
Re: A Game Boy game that emulates a more advanced CPU
« Reply #4 on: February 06, 2019, 11:15:44 PM »
Interesting. So you've personally tested this out on an actual Game Boy?

I don't see why someone would target 24-bit architecture. Plus most of your own code is targeting 8-bits or 16-bits anyway, so it would make more sense to target 16-bit over 24-bit.

What value would there be to target 24-bit? I doubt a Gameboy had sufficient memory available or a powerful enough CPU to make it worthwhile to target a higher architecture than 16 bit.
Currently working on Cataclysm of Chaos, Remade.
Link to OPU page = http://forum.outpost2.net/index.php/topic,6073.0.html

Offline Crow!

  • Newbie
  • *
  • Posts: 29
Re: A Game Boy game that emulates a more advanced CPU
« Reply #5 on: February 07, 2019, 03:38:00 AM »
I see two likely reasons for the 24-bit nature to be selected.  First, it allows math that balloons in size near the middle of a calculation - for example, there are a lot of percentages used in the game's combat math, so this allows a 16-bit integer to have a percentage taken by just multiplying it by the percentage then dividing by 100.

Second, although the game boy itself has a paltry 8kB of RAM, the ROM of the cartridge can be much larger.  FFL3 itself uses a 256kB ROM, which is divided into 16 banks of 16 kB, of which two are accessible at a given time.  Although the code I've touched didn't have to do this, the game in principle has to frequently jump between banks, so letting a 24-bit virtual machine handle bank switching whenever needed would allow them to act as if they could address anything in the ROM directly.

I don't have the hardware necessary to hook up my modified code to a physical game boy, but it runs fine on an emulator.  I use BGB as my game boy emulator for debugging purposes.
« Last Edit: February 07, 2019, 03:45:27 AM by Crow! »
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline lordpalandus

  • Hero Member
  • *****
  • Posts: 733
Re: A Game Boy game that emulates a more advanced CPU
« Reply #6 on: February 08, 2019, 05:19:47 PM »
Well, the reason I ask about testing it on an actual Gameboy is because modern computers have tons of available memory and memory with a much higher hertz than the Gameboy. So even if your code is still within the memory limits of a Gameboy doesn't mean that it would work on an actual Gameboy.

I think Leeor would be less skeptical if it was proven that what you say works for the emulator, also works for the actual hardware of a Gameboy. Otherwise it is purely theoretical speculation.

Much like that whomafu (the guy never spelled it for me, but that is what it sounded like) that a kid told me about in 7th grade, that was a secret unit in the original starcraft (pre-brood war; basically it was supposed to be like the Lurker, but didn't have to unburrow to move). I tried to reproduce the steps they suggested to spawn the unit (gather 10,000 minerals and gas, get a hydralisk and an infested terran and then hit Shift+Alt+C to activate the hidden morph command) and I never could get it to spawn. If they had instead proven to me, by playing a game of StarCraft and spawning the creature, then I would have know it would work. I was skeptical then that the guy was scamming me, but that was the last time I saw the guy so never could ask him about it again. And google searches for something that isn't probably spelled right doesn't come up with anything either.

So, basically what I'm trying to say is that if you say something far-fetched, then it is best to provide solid proof it actually works otherwise you are going to be surrounded by a crowd of skeptics that think you are pulling their leg. Not saying you are, but it has been my experience that with far-fetched stuff (the whomafu wasn't the first or the last time I ran into far-fetched stuff) that the more far-fetched it sounds, the more likely it isn't true.
Currently working on Cataclysm of Chaos, Remade.
Link to OPU page = http://forum.outpost2.net/index.php/topic,6073.0.html

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 2138
    • LairWorks Entertainment
Re: A Game Boy game that emulates a more advanced CPU
« Reply #7 on: February 08, 2019, 05:52:46 PM »
Well, the reason I ask about testing it on an actual Gameboy is because modern computers have tons of available memory and memory with a much higher hertz than the Gameboy. So even if your code is still within the memory limits of a Gameboy doesn't mean that it would work on an actual Gameboy.
This is irrelevant. Emulators emulate the exact environment of a given hardware setup. They're not perfect but for all intents and purposes they're accurate -- what the host's hardware configuration is has no bearing on the emulated environment.

I think Leeor would be less skeptical if it was proven that what you say works for the emulator, also works for the actual hardware of a Gameboy. Otherwise it is purely theoretical speculation.

My skepticism comes from knowing the limitations of the GameBoy... but Crow! has explained things in a way that I'm less skeptical. I'd like to see an assembly breakdown of the VM environment but I don't really have the time for it... basically saying it's emulating a higher bandwidth CPU is a bit of a stretch but from what I can tell it's doing some interesting things that could work on the 8bit CPU of the GameBoy.

So, basically what I'm trying to say is that if you say something far-fetched, then it is best to provide solid proof it actually works ... snip ...

He demonstrated how it could hypothetically works and knowing the hardware it might make sense. I would still like to see a disassembly of the code (assuming it's not obfuscated) and see if I can get an idea for it all.

Second, although the game boy itself has a paltry 8kB of RAM, the ROM of the cartridge can be much larger.

This. This right here is how so many games back on the NES/GameBoy/Etc. which had extremely limited resources could do things that the base hardware could never possibly do. It's a technique known as bank switching and on the NES they used what were called memory mapper chips (MMC). Nintendo provided the MMC1, MMC2, MMC3, MMC4, MMC5 and MMC6 (MMC3/6 [they're almost identical] is the most well known as it's used in Super Mario Bros. 3, it's what allows the static HUD at the bottom of the screen as well as vertical and horizontal scrolling at the same time, something the NES isn't capable of on its own).


That square chip at the top center of the PCB is the memory mapper chip.

The two large chips on the bottom are the Character ROM (graphics connected to the PPU chip in the NES) and Program ROM (connected to the CPU in the NES). This is what most NES games have. The small chip on the top left is the NES10 lockout chip (Nintendo's awful way of trying to prevent piracy). The last chip on the top right is additional RAM for use by the program. That's the interesting part -- this is the extra RAM that is built into the game's PCB that allows it to do way more than the NES would otherwise allow. Side note, HOLY SHIT is it slow! 100ns response time, yeeeeeeesh!

Anyway, GameBoy games are just as capable of using additional RAM chips like this. Hell, I wouldn't be surprised if they added an additional CPU core if they really needed it -- the SuperNES was well known for this via the SuperFX chip. It was basically an additional CPU that was dedicated to graphics manipulation and is what allowed for 3D graphics on the SuperNES (Sega's Virtua Processor was similar for the single game, Virtua Racing, that used it).

To sum up (for real this time), additional hardware on the cartridge would make this very possible. I'm just curious what hardware was on the PCB and how they mangaged the bank switching to make it work.
« Last Edit: February 08, 2019, 06:09:29 PM by leeor_net »

Offline Crow!

  • Newbie
  • *
  • Posts: 29
Re: A Game Boy game that emulates a more advanced CPU
« Reply #8 on: February 08, 2019, 06:01:15 PM »
There are indeed some emulators that are irresponsible and effectively enhance the capabilities of the simulated machine.  ZSNES is probably the most famous one in this regard; all lag that games experience completely disappears when played on that emulator.  The emulator I used is called BGB, and the romhacking / tool assisted speedrunning communities regard it as pretty accurate.  (Another popular emulator for Game Boy games, Virtual Boy Advance, is not.)

If you would like to test things out yourself, go right ahead, and let me know how it goes!  Here's a link to the RHDN entry for my hack (it got accepted yesterday):
http://www.romhacking.net/hacks/4351/
Speedruns, my FFIV game randomizer, and more can be found at my twitch page:
https://twitch.tv/iicrowii

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4688
Re: A Game Boy game that emulates a more advanced CPU
« Reply #9 on: February 10, 2019, 10:19:06 AM »
Hmm, interesting site.

And that's not so much ASM as it is machine code. Way more cool when you can program with machine code.  8)

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 2138
    • LairWorks Entertainment
Re: A Game Boy game that emulates a more advanced CPU
« Reply #10 on: February 10, 2019, 06:25:17 PM »
ASM and machine code are basically the same thing. :P :P :P

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4688
Re: A Game Boy game that emulates a more advanced CPU
« Reply #11 on: February 12, 2019, 04:32:33 AM »
A near 1-1 correspondence, yes, though a huge difference in terms of user friendliness.

Yes, it gets worse than assembly language. ;)

Offline leeor_net

  • Administrator
  • Hero Member
  • *****
  • Posts: 2138
    • LairWorks Entertainment
Re: A Game Boy game that emulates a more advanced CPU
« Reply #12 on: February 13, 2019, 12:59:11 PM »
Well, if we're going to go down the rabbit hole, it gets worse than machine language, we could just code things in straight up binary. :P

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4688
Re: A Game Boy game that emulates a more advanced CPU
« Reply #13 on: February 16, 2019, 12:54:17 AM »
Toggle switches? Ohh, a magnetized needle and a steady hand! Or maybe just butterflies.

https://xkcd.com/378/


Hmm, as I've just learned, Emacs has received an update after that comic was published: