<![CDATA[Ramblings of an Infectious Disease]]>https://blog.pathogenstudios.com/Ghost 0.11Thu, 31 Dec 2020 00:36:13 GMT60<![CDATA[Legitimizing your counterfeit Zelda save]]>I've been working on filling the gaps in my collection of the Legend of Zelda franchise, my favorite video game series. One of the gaps I had was The Legend of Zelda: The Minish Cap for the Game Boy Advance. Since the game came out in 2005, I was stuck

]]>
https://blog.pathogenstudios.com/legitimizing-your-counterfeit-zelda-save/172b98f6-eeda-4b12-b30f-a0ef4b81aabbMon, 17 Nov 2014 02:42:17 GMT

I've been working on filling the gaps in my collection of the Legend of Zelda franchise, my favorite video game series. One of the gaps I had was The Legend of Zelda: The Minish Cap for the Game Boy Advance. Since the game came out in 2005, I was stuck with getting a used copy if I wanted to play it on the GBA. Unfortunately, little did I know, Minish Cap is one of the more frequently counterfeited GBA games. Also unfortunately for me, I didn't even realize I had purchased a counterfeit until I had gotten around 90% of the way through the game...whoops.

As soon as I realized my mistake, I read up on avoiding fake GBA carts and ordered a new copy. Unfortunately, the damage was done. I was already mostly done with the game, and some parts of the game were not completable due to either a bad version of the game or some sort of copy protection.

Legitimizing your counterfeit Zelda save It is surprisingly obvious seeing them side-by-side. Especially the quality of the printing on the label. Additionally, the ESRB and Nintendo logos are wrong. It is also missing the imprinted numbers. Fake on the left, in case you couldn't tell.

I knew when I ordered the new cart that I would try to transfer the save (using homebrew on a Nintendo DS.) The most popular homebrew for doing this is Rudolph's GBA Backup Tool. While it worked fine for pulling the ROM images (for analysis) and the legit cart's safe, when I pulled the save from the pirate cart: I got 8 KB of 0xFF. This was disappointing, but I wasn't going to give up there.

Legitimizing your counterfeit Zelda save I mean, the pirated cart had an impossible-to-reach heart piece in it! You can't just leave those behind!

Diagnosing the undownloadable save

The truth lies within the cart:

Legitimizing your counterfeit Zelda save

As before, the pirate cart is on the left. A battery hints at an SRAM save backup, and this is confirmed by reading the chip model information below. If you look at the real cart, it uses an EEPROM. Unfortunately, the only (reliable) way to detect cart backup media is to look for magic strings placed by Nintendo's build tools. My guess is Rudolph's tool uses this technique, and incorrectly identifies the cart as an EEPROM cart.

Pirate chip info

  • The bigger chip in the pirate cart is a "FUJ1TSU DEVICES INC MSP55LV128T" (Seriously, it's a knockoff of a Fujitsu chip.)
    • I had trouble getting info on this chip, but it is most definitely the ROM chip.
    • Here are some Russian dudes talking about it: http://www.ezoflash.com/forum/viewtopic.php?f=4&t=9673
    • Google Translate suggests they know it is 16 MB but can't figure out the pinout.
    • 16 MB adds up since the 128 in the model number probably means 128 MBit. (Minish Cap is 16 MB too.)
  • Smaller chip under battery is CY62128EV30
    • 1 MBit static ram (128 KB)
    • Minish cap's save is only 8 KB, so this is a bit of a waste.

Legitimizing your counterfeit Zelda save

Those with sharp eyes will also notice in the above screenshot that the pirate cart is GBAZELDA_MC_BZMP, which is the PAL region (European) version of the game. I live in the US though and should (as the cart has on its label) GBAZELDA_MC_BZME.

When doing some analysis on the ROM dumps, it appears that it definitely the PAL version of the game. Additionally, the entire ROM is doubled. I imagine this is either an error in Rudolph's tool or the pirate cart's design (the real cart didn't do this.) Other than that, there are two other small changes:

Legitimizing your counterfeit Zelda save

I didn't have the patience to disassemble this (don't blame me, blame THUMB mode), but I imagine these are save file routines. (Patching from EEPROM to SRAM is actually very automated from the little I know. There are tools out there from when the reloadable GBA carts didn't have EEPROM chips or support emulating it.)

So at this point I am starting to worry. I tried a handful of other save dumpers with similar results. Additionally, even if I got the save down, there's no telling if it is going to work because of the separate regions. (I could've tried loading a pirate save from an emulator on the legit cart or with the legit rom in an emulator, but I decided against this since the following was more fun.)

The Solution

So what would any sensible* person do in this situation? Give up. Make their own save file dumper from scratch. (There is actually an open source save downloader on GitHub, but for various reasons I ignored it.)
*For various definitions of sensible.

So with reading my trusty hardware reference and reinstalling the ever-reliable devkitPro I set out on my quest.

I started with a simple Nintendo DS tool that could print out the contents of a GBA save file. Basically, a simple hex viewer. I'm lucky that the pirate cart was SDRAM instead of EEPROM rather than the other way around, because reading from SRAM is dead simple while the EEPROM...not so much (from what I've gathered.)

All you have to do is clear bit 7 of the EXMEMCNT register to give access to the ARM9 processor to the GBA slot. (The Nintendo DS has two processors, an ARM9 and an ARM7.) Then, the SRAM can be accessed using 8 bit reads in the address range 0x0A000000 - 0x0A010000, which is the "GBA Slot RAM" (previously known as the Game Pak SRAM at 0x0E000000 in the GBA.)

Clearing bit 7 in EXMEMCNT is pretty important, because if you forget you will get all 0x00. Which is not awesome. (This is why the app has the EXMEMCNT displayed and a message stating whether the entire save region is 0x00 or 0xFF...oops.)

Legitimizing your counterfeit Zelda save

As you can see, the app properly detects the game's name, and can read its save data. It is backwards, but you can also see that the save data begins with the text "ZELDA". I'll talk a little bit more about this later.

Legitimizing your counterfeit Zelda save

You can also see my nickname "Path" in there (also backwards.)

At this point we know we can definitely read the save data, so now we just have to save it to the flash cart. I was actually pretty surprised I didn't need to mess with waitstates or anything like that.

I did end up copying the data "by hand" 1 byte at a time into a temporary buffer since GBATEK states that the SRAM only has an 8 bit bus, and I figured memcpy and fprintf might not use 8-bit reads in devkitPro. (If I was feeling hard core, I would've done it in assembly to be extra sure.)

Shuffled save data

I actually ended up finding this wasn't completely necessary, but I thought I'd cover it anyway.

For reasons not completely clear to me, the save data in EEPROM games is partially backwards. To be more exact, each chunk of 64 bits is reversed. The 64 bits makes sense since you access the EEPROM 64 bits at a time, but why the reverse? I am thinking it might have to do with how the generic Nintendo EEPROM code works. (It also turns out that Rudolph's GBA Backup Tool ships with a VBS script to fix it for you.)

If you compare the two raw save files from NO$GBA, you'll see that the real version (bottom) is linear, but the pirated cart is reversed.

Legitimizing your counterfeit Zelda save

I imagine this is because the Nintendo save routine is still writing everything backwards, but NO$GBA isn't reversing it for the raw save because its SRAM and not EEPROM. Or maybe EEPROM is naturally recorded backwards. Either way, I wanted to be able to test my dump save in an emulator before loading it on the real legitimate cart. So as a part of this project, I also wrote a small C# tool to fix the orderings of the dumped save files.

Small side notes about the saves

This is a bit out of place, but I found it interesting so I wanted to mention it. From a very light look at the dumped saves, it looks like Nintendo/Capcom are storing each save file twice. I imagine this is to ensure one version of the save file is still available if one gets corrupted by the player removing the cart or old hardware. You can corrupt one, but not the other, and still get a proper save in game.

Of course, if you mess with both of them, you get a dreaded error that I imagine most players will never see.

Legitimizing your counterfeit Zelda save

So there's definitely some crazy CRC action going on. Also interesting, the game takes a noticeably longer period of time at the start screen when the save file is corrupted. I guess it is either a pretty thorough integrity check, or maybe there's some error correction going on.

Loading the pirate save into a legit game

At this point, if I loaded the pirate save into the legit game in an emulator, I only got a blank save screen. (Interestingly, no error on the screen.) So I had to look at what was different between the two games' saves (and hope it wasn't everything.)

Legitimizing your counterfeit Zelda save

There's only a few bytes different here and there, and they are all in that little header section. One difference in particular stands out, the difference in the game title string at the start of the save: "ZELDA 3" vs "ZELDA 5". I imagine this is some sort of internal version number. All I did was change the 3 to a 5, and load it in the English version of the game and...

Legitimizing your counterfeit Zelda save

We have savefiles! After this, I tried to load it on the real cart. Since I knew it worked with the real cart, I just used Rudolph's GBA Backup Tool again. Since the save it dumped from my real cart was shuffled, I took this as a hint to give it a shuffled version (but still with the corrected version number.)

Legitimizing your counterfeit Zelda save

Source code

Even though it isn't much, I've open sourced the code for both my little NDS SRAM save viewer/dumper as well as my little C# tool for un/reshuffling save files. You can find the source code for both on GitHub under PathogenDavid/PathogenBackup. Both projects are contained in a Visual Studio Solution. The NDS project is an NMake project, so if you don't have Visual Studio you can just run the makefile as you normally would (provided that you have devkitPro installed.) I imagine both projects should build/run fine on Linux and Mac, but I have not tested this.

Legitimizing your counterfeit Zelda save

Post cover is a parody of the Nintendo Anti-Piracy website header. Nintendo and Mario are trademarks of Nintendo Ltd.

]]>
<![CDATA[Rolling your own breakpoints without 0xCC]]>Some time ago, I had the need to interrupt the execution of a program at very specific instruction addresses in code. Basically, I needed to implement breakpoints from scratch. You will probably never want to do this, and that's completely normal. However, it is an interesting thing to know about,

]]>
https://blog.pathogenstudios.com/rolling-your-own-breakpoints-without-0xcc/e83a1ce8-d16b-4cc2-9de4-bd09f0b5ff67Mon, 22 Sep 2014 08:47:20 GMTSome time ago, I had the need to interrupt the execution of a program at very specific instruction addresses in code. Basically, I needed to implement breakpoints from scratch. You will probably never want to do this, and that's completely normal. However, it is an interesting thing to know about, and if you are some explorer from the internet who wants to implement breakpoint-like functionality without 0xCC, then you're in the right place!

First, a little about how breakpoints are implemented in your favorite C++ debugger on x86 platforms...

How breakpoints work

Most people don't know how breakpoints work at the core. You hopefully at least know that breakpoints will stop your program whenever it hits a specific line of code. If you've done much at the assembly level, you probably know they actually stop when you hit a specific processor instruction. But how are they implemented? You may find the solution to be surprisingly simple.

I'm going to assume that you know that code is compiled down into assembly code, and have a basic understanding that assembly code is essentially human-readable machine code.

So say we have the following assembly code for a function that adds 2+5 and returns the result: (The code bytes are shown on the left.)

B8 05 00 00 00      mov eax,5  
83 C0 02            add eax,2  
C3                  ret  

Now say I want to place a breakpoint on the add instruction. The way the debugger implements this is that it rewrites the code in place in memory. Specifically, it replaces the add instruction with int 3.

B8 05 00 00 00      mov eax,5  
CC                  int 3  
C0 02               ; Effectively garbage  
C3                  ret  

When the int 3 instruction is hit, the breakpoint interrupt is called, which then notifies the debugger attached to the application. The debugger will let you know the breakpoint is hit, let you do your thing, and before you resume the program it will replace the old instruction.

Unfortunately, the process behind rewriting the instruction is out of the scope of this post. There are various tutorials out there on the internet, so you can look at them. If you're comfortable with reading reference material, the general process is:

  1. Enable writing on the code segment
  2. Save the old instruction, write int 3
  3. Flush the instruction cache
  4. Disable writing again.

There's a bit more to it, like getting the application into a suspended state, but that should get you started.

Why int 3 is special

What is so special about int 3? As you may be able to guess, the int assembly instruction simply causes the processor to call the given interrupt.

int 3 is extra special though. Normally, an int instruction is two bytes: 0xCD 0x03. However, the x86 instruction set has a special opcode specifically for int 3 which is only one byte: 0xCC. Intel's x86 developer's manual describes it as "Interrupt 3—trap to debugger."

This makes is very ideal for replacing other instructions, because some instructions (like ret) are only one byte long. If we replaced ret (0xC3) with a two byte instruction, we would be overwriting unrelated code that follows the ret (probably the prologue of another function.)

Why I couldn't use int 3

Unfortunately, for my particular use case, I couldn't use int 3! Why? For this specific project, we needed to be able to use the Visual Studio debugger on the program as it ran. In Windows environments, int 3 always goes straight to the debugger if one is attached. You can't even intercept it with a vectored exception handler!
(If a debugger isn't attached though, you can capture the int 3 as an EXCEPTION_BREAKPOINT exception.)

So therefore, I needed a similar solution that still met the requirements that int 3 does for debuggers.

  • Must be one byte instruction*
  • Must cause execution to jump to a specific point
  • We must be able to resume execution as normal afterwards

Quite the tall order!
*Or, a multi-byte instruction that isn't affected by the operands as far as we care.

The quest for another method

Long story short, there is actually an instruction that meets criteria: The hlt instruction! This instruction is normally used to halt the processor and stop execution. However, it is a privileged instruction. When you call it from unprivileged code, the processor fires the #GP(0) exception. On Windows, this will cause your vectored exception handler to fire with a EXCEPTION_PRIV_INSTRUCTION exception. (On Linux and friends, you receive SIGILL.)

So if you implement breakpoints exactly like a debugger would, but with the hlt instruction, you can co-exist with other debuggers manipulating your code.

Is this a hack? Yes. Does it work? Yes. If (for whatever reason) you find yourself wanting to have breakpoint-like functionality without using the 0xCC instruction, now you know how! Uhh...but don't try it in a kernel mode driver. That'd probably not go well.

Of course, there is the theoretical problem of what happens when you and the debugger start fighting over a specific instruction, but we weren't too concerned about this situation in our case.

Sample code

Here's a simple example of this concept in use. In this example, I left out all of the debugger-like stuff in favor of having the hlt instructions placed at compile-time.

This sample simulates round-robin cooperative thread-switching in a Windows application.

//A simple example of using the hlt instruction to trigger a context switch
//NOTE: You should never actually use this as a method of thread cooperation.
//This is an example from https://blog.pathogenstudios.com/rolling-your-own-breakpoints-without-0xcc/
#include <stdio.h>
#include <Windows.h>
#include <assert.h>

#define NUM_THREADS 2
static HANDLE threads[NUM_THREADS];  
static int currentThread = 0;

#define HLT_INSTRUCTION 0xF4

LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS exceptionInfo)  
{
    //If the exception isn't EXCEPTION_PRIV_INSTRUCTION, or the instruction that caused the exception isn't HLT, we don't do anything:
    if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_PRIV_INSTRUCTION
        || *((unsigned char*)(void*)exceptionInfo->ContextRecord->Eip) != HLT_INSTRUCTION
    )
    {
        return EXCEPTION_CONTINUE_SEARCH;
    }

    //Advance past the hlt instruction: (Normally, you'd just restore the old instruction instead.)
    exceptionInfo->ContextRecord->Eip++;

    //If this was a HLT, we do a "task switch":
    int previousThread = currentThread;
    currentThread++;
    if (currentThread >= NUM_THREADS) { currentThread = 0; }
    ResumeThread(threads[currentThread]);
    SuspendThread(threads[previousThread]);

    return EXCEPTION_CONTINUE_EXECUTION;
}

DWORD ThreadMain(int threadNumber)  
{
    while (1)
    {
        printf("Thread %d is running...\n", threadNumber);
        printf("Thread %d is switching away...\n", threadNumber);
        __asm hlt;
        printf("Thread %d is waking up!\n", threadNumber);
    }
}

int main()  
{
    //Register the exception handler:
    void* exceptionHandler = AddVectoredExceptionHandler(1, VectoredHandler);
    assert(exceptionHandler != NULL);

    //Create the threads:
    for (int i = 0; i < NUM_THREADS; i++)
    {
        threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadMain, (LPVOID)(i + 1), CREATE_SUSPENDED, NULL);
        assert(threads[i] != NULL);
    }

    //Start the first thread and wait for all threads to exit:
    assert(ResumeThread(threads[0]));
    assert(WaitForMultipleObjects(NUM_THREADS, threads, TRUE, INFINITE) != WAIT_FAILED);

    //Cleanup:
    for (int i = 0; i < NUM_THREADS; i++)
    { assert(CloseHandle(threads[i])); }
    assert(RemoveVectoredExceptionHandler(exceptionHandler));
}

If you run this program, you'll see that the two threads never run at the same time. The output will show one thread running after another.

(NOTE: As stated in the documentation for SuspendThread, you shouldn't ever actually do this. Although SuspendThread is probably safe in this situation, you're much better off using synchronization objects or some other thread cooperation method.)

]]>
<![CDATA[Blog 5.0]]>If you've been following me for a while (Hi Mom, I love you!) then you probably know that I have a really bad habit of falling out of maintaing my blog. I think the main reason is a lack of direction. I never really knew what I wanted out of

]]>
https://blog.pathogenstudios.com/blog-5-0/62d35cd7-6aa2-4dc2-b8da-28bd78190803Mon, 22 Sep 2014 05:51:34 GMTIf you've been following me for a while (Hi Mom, I love you!) then you probably know that I have a really bad habit of falling out of maintaing my blog. I think the main reason is a lack of direction. I never really knew what I wanted out of having a blog. I just kinda had it because I felt like I was epxected to have one.

Today as I was catching up on the parts of the Oculus Connect steam that I missed, I decided to go look up Michael Abrash. I knew his name, that he was a pretty smart guy, and that he worked at Valve and was now at Oculus. Unfortunately, that was about it.

I quickly stumbled into his (now defunct?) blog Ramblings in Valve Time and started reading his article on judder in VR. However, I ended up getting more than just some new knowledge about VR. Michael started the series with a discussion/argument in favor of sharing information. His discussion made me realize why I always got bored of maintaining my blog.

All of my blog entries have been geared towards "normal people". They weren't technical, they were mostly about for games I was working on in my spare time. The primary issue with this is it makes my writings fairly useless. They don't benefit anyone other than me. If I am honest with myself, they aren't even very interesting unless I gained a following and had demos to play or something.

So what does this all mean for this blog?
From now on, this blog will be 99.9% technical. I may talk about something more personal from time-to-time, but for the most part the blog posts will be unrelated technical how-tos and discussions.

Hopefully I can keep myself interested this time around!

]]>