![Huang Di](https://cdn.statically.io/img/images.timeextension.com/1236e864ad420/huang-di.900x.jpg)
Have you played the unlicensed Taiwanese game Huang Di: Zhuo Lu Zhi Zhan on Famicom / NES? If you have, you already know about the weird "infinite jumping glitch" where your character flies around if the jump button is held. It removes any challenge and breaks the game. Well, the problem has been fixed and I'm going to explain how I did it. If you just want the patch without the story, scroll to the bottom.
If you've not played Huang Di (the full title of which translates as Yellow Emperor: Battle of Zhuolu), then you should. It's one of the absolute all-time best unlicensed games for the system. There are a lot of interesting unlicensed games available, such as the Resident Evil and Final Fantasy VII demakes, but Huang Di is unique because it's not based on another game, but rather the real-life mythical sovereign that is the Yellow Emperor.
It therefore features all sorts of cool set-pieces and monsters based on ancient legend, backed by some great music. It's also a very challenging action platformer when played correctly – the various "speedruns" you can see online are quite amusing, since they've obviously playing the bugged version. I first wrote about Huang Di for Retro Gamer many years ago (that screenshot is doctored to show more enemies than normal), and then again for Hardcore Gaming 101. In fact, I love it so much that I was determined to find a way to play it as intended. But first, some background...
Back in 2012 when writing the HG101 article there was a discussion as to whether this was actually a bug or intentional. Given the in-game cinemas show the main character flying around on a sword, one reader hypothesized that perhaps you're meant to fly. Various emulators reproduced the problem, and it was only after reader Ghegs tracked down an original Famicom cartridge that was it proven not to occur on real hardware. Simple then, it's obviously just an emulator glitch that doesn't occur on real hardware. Once we had cycle-accurate NES emulators, it would probably go away, similar to how emulators couldn't display the shadow in Air Strike Patrol on SNES until we had HIGAN.
I then purchased a NES PowerPak flash cartridge to play the game on my original NTSC toaster NES without this glitch (in 60Hz!). Huang Di worked correctly. However, sometime between 2012 and now, various new mapper sets were updated as they became available, culminating in 1.35b, plus Loopy's extra mappers, plus TheFox's power mappers, plus some other miscellaneous additions. (I also thought maybe I'd upgraded the firmware, but this turned out not to be the case.) Anyway, after various file updates, the game broke again. The same glitch of infinite flight.
Well, simple solution, right? Just erase the memory card and reinstall the older mappers. First was the immediately previous folder of mappers, since I always kept a backup in case something went wrong. No good. NES PowerPak maker RetroUSB still has available older legacy mappers for v1.20, but after playing around with the URL link, I managed to access their hidden archive of v1.00. Several hours later, after multiple erasures and reinstalls, and Huang Di still didn't work correctly.
Do you ever have a situation where you think you remember something one way, but then the evidence proves it's the other way, so you just assume you remembered wrong? I was starting to think maybe Huang Di never worked on the PowerPak, and I just imagined it... Except no, I posted online about it working, so the memory was real.
Hours were spent researching the problem. Huang Di uses INES Mapper 112, the name of which is converted to hexadecimal for PowerPak's menu folder, and is named MAP70.MAP – however, every single mapper release for the PowerPak produced the same problem. Maybe it was the firmware at fault? But how, and why? Had I updated it? Is it even possible to downgrade cartridge firmware, or would this brick it?
RetroUSB was duly contacted, and they explained:
"The actual firmware on the cart is not user updatable. There is nothing you did to reprogram the PowerPak itself. The only thing I can think of is you had an alternate mapper file, there was some sort of modification to the mapper file, or you were using an alternate ROM that had a modification."
The solution seemed so tantalisingly close. Perhaps one of the hackers on either Romhacking or NESDev may have an idea? Forum user Rainwarrior on NESDev, back in 2016, actually posted information that would lead us to the answer. He posted an excerpt from someone's commentary on NES emulator FCEUX. The emulator, when started, initialises the RAM to a string of 00 and FF. It basically wipes the RAM clean. Someone worked out that Huang Di expects the RAM at address 0x0100 to return a non-zero number. If the number is zero it defaults into debug mode – presumably so the developers could test it more easily.
It turns out the infinite jumping glitch is not really a glitch; it's an intentional debug mode that is being triggered by accident. But how to fix it on the PowerPak? I asked again about the mappers.
NESDev user Dwedit explained in detail:
"This has nothing to do with mappers at all, and entirely to do with uninitialised memory. The game never writes anything to location 0100, but is reading that byte back. The value could literally be anything, because initial values of uninitialised RAM are based on environmental factors such as static charge and ambient temperature, previous values of the memory, and just how that memory cell happens to be constructed. In order to have things be nice and deterministic, emulators will clear the system RAM to known initial values. FCEUX repeats a pattern of 00 00 00 00 FF FF FF FF that leaves the RAM at 0100 as having a value of 00."
Well, all we needed then was to make sure the RAM at 0100 is not zero. My initial hope was a Game Genie code. The device functioned by changing variables in-game, and the PowerPak had built-in Game Genie functionality, so... easy, right? One just needed to figure out the code using one of several utilities. Except this was not possible, as pointed out by Cyneprepou4uk on RHDN: "It's a RAM address at 0100. Game Genie doesn't modify RAM directly. Emulator cheats do."
Cue more research, and... that's absolutely correct, Game Genie can only write to addresses at 8000 and above. There is no way to use a Game Genie to change that initial RAM value. For that, you need to use an emulator, which allows direct manipulation. Still, this did yield one breakthrough. Loading up an NES emulator and putting the following in as a cheat:
30000100 0001 Adr:0x0100 val:1
This completely fixes the problem. By forcibly writing a value of 1 to that specific address, the debug mode is disabled as intended. So why on earth did the PowerPak suddenly stop working?
Dwedit suggested that:
"A flash cartridge may contain code to clear memory as well. This game is programmed to fill 0000-00FF, and 0200-07FF with 00 bytes at boot time, but it does not fill page 0100-01FF. They skipped clearing that page because they were using a subroutine to clear the RAM, and didn't want to clobber the return address. An earlier version of the flash cartridge may have left behind leftover RAM contents from the menu system at the time the game booted. A different version of the menu may have cleared the RAM instead, or left behind different memory values."
Well, if the cartridge was resetting the RAM, and Game Genie couldn't access the RAM, did that mean the only way to play the game was emulation in conjunction with the above emulator cheat code? Thankfully, both Cyneprepou4uk and Dwedit responded with code to hack into the game's ROM using a HEX editor. Interestingly, they each provided an entirely different solution, but both of them work:
Cyneprepou4uk:
At 0x1D391 replace 8D 0F 01 with 20 A3 F7
At 0x1F7B3 replace 00 00 00 00 00 00 00 00 00 with 8D 0F 01 A9 FF 8D 00 01 60
Dwedit:
At 0x1D36E replace A9 00 8D 00 20 8D 01 20 with A9 01 8D 00 20 8D 00 01
After using a HEX editor to hack a clean ROM, using one of the above options, it was easy then to use LunarIPS to compare the hacked ROM to an unedited one and create an IPS patch for legal distribution. The patch even works with the fan-translation of Huang Di!
Both forum users gave permission for the patches to be uploaded, which you can now find here. At last, whatever your means of playing Huang Di, it can be played as intended. In fairness, some emulators correct for this, but not all.
Dwedit and Cyneprepou4uk also provided Game Genie codes if you're unable to patch. The technical explanation of how these work, given the earlier RAM explanation, is too complex to summarise. Just make sure to type all three in:
PASSYLAA
AAVIGLPA
PAVIILAZ
For me, the fascinating part of all this is even though the very first Famicom / NES hardware variation came out nearly 40 years ago (July 1983), we are still discovering things. A decade ago, this curious but wonderful unlicensed game was thought to have a glitch. It turned out simply to be a debug mode activating due to the RAM starting at zero. This itself leads to other interesting points, like the fact Metroid uses the initial RAM in its RNG – so is resetting the RAM to zero in an emulator truly accurate when on original hardware, this is not the case?
Regardless of the minutia of this technical rabbit hole, please enjoy the patches I created with the help of Cyneprepou4uk and Dwedit. (Oh, and can someone tell the speedrunners they're playing it wrong and all their times are void unless they play with debug mode off?)
Comments 11
The journey to solve this "glitch" was quite interesting, thanks for sharing the various possible solutions for those interested in playing this game without debug mode on (and also for making those who hadn't heard of it at all before like me discover it)!
Uninitialized memory causing debug modes to be activated accidentally.
I remember some people claiming Super Mario All-Stars for SNES having a debug mode for SMB3 activated (in that case giving the ability to change Mario's form at will with Select, which in effect gives invulnerability), which turned to be accidentally based on the user's console RAM and/or how the cart SRAM had gotten randomly filled at the factory. I think it was determined after one of the users reporting claimed they had a "bugged" copy back in the day, and then they played the cart again many years later and it stopped giving them the debug functionality.
This is a neat story, but it just highlights that there's still a lot to find in older games. I have a similar example that didn't affect gameplay but was still curious.
Core Design's Wolfchild was released for a number of platforms: Amiga, SNES, Mega Drive, Master System, Game Gear and Mega-CD. The latter, I think, was the best version, with improved level design and a campy soundtrack (but the less said about the intro, the better).
But the SCD version was released with a bug. In the Megadrive version, the 2nd level included mountains on the horizon and a scrolling background. The Mega-CD version, based on the Megadrive version, did not include the same. Almost nobody mentioned this in the reviews of the game at the time. Leave it also to the self-proclaimed "retro gaming specialists" who swell YouTube with retrospectives, longplays and overly long videos about the same games over and over never mentioning the obvious.
I found this strange. I went to the game code and everything was there: the graphics, the graphics table, everything. But the level simply refused to load all the data into memory.
Then I noticed that there was a discrepancy between the data in the ToC (Table of Contents, which in Mega-CD defines where the data sectors are) and the amount of information that was actually read from the declared amount.
It was reading less data than it was supposed to. The error was in one single, measly byte. One. Byte.
After contacting one of the original devs about this and receiving no answer, I fixed it myself and released a patch on RHDN for all CD versions (US, Euro and Japanese).
I just find it funny that this went unnoticed and unresolved for 28 years, and everyone assumed everything was just okay.
Fascinating! Looking at the asm from the link the patch changes the ROM to load 1 into the accumulator and then store it at the memory address the game checks for debug mode. I recently did something similar messing with Street Fighter II Turbo on the SNES to always get the best ending regardless of difficulty or rounds lost. I’ve found writing assembly isn’t too tricky, but finding the right part of the ROM is really hard!
NES RAM initialization is very interesting to learn about, particularly that games will have behaviour that assumes the console boots with RAM in an uninitialized state.
Super Mario Bros makes use to this so that the A+Start trick to continue a world from game over does not persist when you turn the console on after being powered down.
Pressing the reset button for a warm start (aka soft reset) versus pressing the power button for a cold start (aka hard reset).
It turns out that the NES game Tennis writes to the same address in memory for SMB's A+Start trick, and that if you play SMB, then Tennis, then SMB, by physically swapping the cartridges whilst the console remains powered on, that you can tamper with RAM initalisation and get access to invalid world IDs.
https://www.youtube.com/watch?v=hrFHNgJlJSg
So yeah, for Huang Di here, it sounds like an error in uninitialised RAM handling. It's entirely possible, likely even that the Taiwanese developers were using unofficial "Famiclone" hardware that did not handle uninitialized RAM in the same way as official NES or Famicom hardware.
Something like a Dendy, a Micro Genius, etc.
I would suspect that's the root of the issue, trying to play unofficial software developed on unofficial hardware, on official hardware or emulators targeting cycle accuracy of official hardware.
@killroy10 And a fine job you did too, it turned the Mega CD version into my favourite port of the game! Thanks for your hard work. People like you are keeping retro gaming alive
@AJB83 I'll be honest, I had no idea it would be appreciated by anyone. I'm glad you liked it, and I'm glad you told me - it actually means a lot to me. Thank you ^_^
@killroy10 Absolutely, most DEFINITELY appreciated on this end!!!
Great story! Now…..all you need to do is localize the language….!
this is good stuff
@killroy10 Well done and thank you for your efforts making a patch! There's a few examples of obscure little bugs like this - SMB2 on NES is another, in that it incorrectly skips out on a frame of animation unless patched. As you say, there's not always much (if any) coverage of the minutiae like this, so it's up to enthusiasts like yourself to provide solutions. I'll be looking into this one.
@Magrane There is a fan-translation for Huang Di by another person, and it's compatible with the jump fix, so you can apply both and enjoy it in English.
Tap here to load 11 comments
Leave A Comment
Hold on there, you need to login to post a comment...