Category: hacking

  • Anatomy of a Hack

    A “ROM hacking 101” tutorial by Cubear

    Cubear’s projects include the fan-favorite DressCode mod for Final Fantasy V, and numerous MSU-1 hacks including for Donkey Kong Country 2 and Live A Live, just to name a few. You can follow Cubear’s work via YouTubeX. or Patreon.

    What is a hack? (game modification)

    There’s hacks that adjust data, and there’s hacks that adjust code. (or code and data)

    This document is about the latter. No shade on the former, it’s valid, but it’s not what I do so I can’t comment upon the process.

    In essence, an ASM hack, assembly hacking, or whatever you want to call it, is a modification of the game’s internal code. You write a bit of code to accomplish a task, you insert it into the game, and voila! You’ve probably broken everything.  Don’t worry, it’s normal and it happens to everybody.

    All this sounds pretty simple, but it takes a bit of getting used to.. for instance, once your code is written, how do you get the game to run it? When?

    Well, to get the game to run your code you’re gonna have to hook.

    So what’s a hook? It’s a place in the code where something is working in a manner you desire, somewhere convenient, somewhere that runs when the function you are trying to alter is running, perhaps.

    So let’s look at a sample bit of code…

    PHA
    ASL
    TAX
    LDA $3100,x
    STA $3E
    PLA
    RTS

    It doesn’t matter what this is doing or not doing. I wrote it at random to be roughly representative of code you might encounter in basically any 6502 game.

    Let’s say the information in $3100,x or $3E were interesting to you. Maybe it’s a map load, or a song’s track number or a spell or item being used…  whatever you want to change, you could change it here.

    So let’s say that you’re changing the number, maybe only on a specific number, like the spell number 0x56, you want to replace with 0x6E, but otherwise let the values pass unchanged.

    Your code might look like:

    CMP #$56  Compare value in A with 0x56
    BNE +     Branch forward if it is not equal
    LDA #$6E  Load 0x6E into A
    +                 Branches merge here

    All in all a pretty simple thing, but unless you tell the game to run your code, it won’t run it!

    So now what we need is a hook.

    On hooks:

    In a ROM, every instruction is an array of bytes. Different instructions will be different sizes, in bytes.

    For example, let’s look at where we’d like to hook.

    PHA – 1 byte. 
    ASL, 1. 
    TAX, 1. 
    LDA #3100,x...?  3 bytes.  
    STA $3E, 2 bytes 
    PLA, RTS? Both 1 again.

    Now, on SNES there are two different sizes of “hook”

    (maybe 3 but we’ll ignore hooking with branches for now since they’re often impractical)

    JMP, JSR are 3 bytes.
    JML, JSL are 4 bytes.

    Shifting bytes around in a ROM is a really hard task. So let’s not do it. Instead, we will overwrite the bytes in the ROM with new bytes.

    So, from looking at where we want to hook, LDA $3100,x seems the smart place. If we can get away with a 3-byte hook, we replace just that one instruction, 3 bytes into 3 bytes, everything is great.

    So let’s do it using JSR.. and you return from JSR with RTS.

    So now the code looks like:

    PHA
    ASL
    TAX
    JSR bankC0free - - - - (jumps to) - - - - ↓
                                            bankC0free:
    					 CMP #$56
    					 BNE +        
    					 LDA #$6E 
    					 +                
    					 RTS
       ↓ - - - - - - (returns to) - - - - - - -
    STA $3E
    PLA
    RTS

    In this way we can run a lot more code during those three bytes than the program originally intended.

    Oh! but there’s a bit of a problem! We erased an instruction and it’s not being replaced!  This means the game will NEVER perform the LDA $3100,x instruction. Let’s correct that. You almost always need to move the code you replaced in order to place your hook, you need to move it into your hook.

    So now our code should look like this:

    PHA
    ASL
    TAX
    JSR bankC0free - - - - (jumps to) - - - - ↓
                                            bankC0free:
    					  LDA $3100,x
    					  CMP #$56
    					  BNE +        
    					  LDA #$6E 
    					  +                
    					  RTS
       ↓ - - - - - - (returns to) - - - - - - -
    STA $3E
    PLA
    RTS

    This will do exactly what we wanted to do in the first place. Compare the value being loaded from $3100,x with 0x56, if it IS 0x56, replace it with 0x6E, and if not, pass the loaded value through unchanged.

    Perfect! But… what if there’s no free space in the same bank? What if we need to use 24-bit addressing, what if we need that 4 byte hook? (this will come up VERY often)

    then it’s time to find 4 bytes to hook with.

    We could hook 4 bytes with

    TAX
    LDA $3100,x

    one byte + three bytes.. four bytes. Nice and simple. Just need to put TAX into your new code area as well.

    Let’s say that’s not an option for whatever reason. What if you need a 4 byte hook but the things around only add up to 5 or 6…? for instance,

    LDA $3100,x 
    STA $3E

    That’s five bytes. If you replace 5 bytes with 4 bytes, the 5th byte remains and it will completely ruin your day.  Luckily there’s a 1 byte instruction you can always overwrite dangling bytes with.

    NOP (no operation)

    Let’s try it now.

    So now your hook area will look like:

    PHA
    ASL
    TAX
    JSL bankFAfree - - (jumps long to) - - - - ↓
                                             bankFAfree:
    					  LDA $3100,x
    					  CMP #$56
    					  BNE +        
    					  LDA #$6E 
    					  + 
    					  STA $3E               
    					  RTL
       ↓ - - - - - - (returns to) - - - - - - -
    NOP
    PLA
    RTS

    So the code we’re replacing got split up in our code block.  This is just because we want to modify what was being written to $3E, so it needs to happen after our code, so it just goes at the END of our code space.

    Alright so now that we know what a hook looks like, how do we write one for ASAR?

    Well, now WHERE in the rom the code we’re replacing is is very important.

    ASAR’s org instruction tells ASAR where to place code, so let’s say LDA $3100,x is in ROM at $C082CE

    Our hook for asar looks like:

    org $C082CE
    JSL bankFAfree
    NOP

    and then we also need to tell ASAR where to put our new code, let’s say FA8000 is completely empty.

    org $FA8000
    bankFAfree:
    LDA $3100,x
    CMP #$56
    BNE +        
    LDA #$6E 
    + 
    STA $3E               
    RTL

    and that’s it. That’s how you hook with ASAR, that’s how you figure out where to hook, that’s everything about hooking to run your own code in a game. Apply your ASM with ASAR and it’ll insert your hook and your code for you.

    This post has been viewed 58 time(s).

  • Spotlight: Jonko the ROM Hacker

    Project Highlights in Fan Translation and More

    Jonko is a ROM hacker and YouTuber whose primary work is with the Haroohie Translation Club, where he serves as project lead and main ROM hacker. He also dabbles with homebrew and emulator development.

    You can follow Jonko via YouTube or website blog explaining how ROM hacking works.

    Jonko sits down with FFV Central to give an exclusive overview of project highlights.

    Subheadings, screenshots, and trailers added during the editorial process.

    0. Intro

    FFV Central: How did you get into romhacking and translating?

    Jonko: Kinda random. I picked up fansubbing (as a script editor) as a hobby at the beginning of covid lockdown. one of our shows was onegai my melody, and i found out there was a DS game for it. I’m a programmer by trade, so I thought I’d give trying to translate it a go. Cracked it open and found out that I just absolutely loved the work involved in figuring out how a game works and building little tools to edit them. I ended up doing a full translation of Sailor Moon: La Luna Splende with a graphics guy and one of my Italian friends, and then eventually founded this project because of a random gbatemp thread

    It just sorta spiraled into a massive effort with a bunch of people involved. Learned a lot as a result of working on it and I’ve developed all sorts of stuff since then. Honestly, pretty life-changing

    You might have seen on the site already, but Will and I developed a full editing suite for Choku based on my reverse-engineering work, which is something I’m very proud of haha

    FFV Central: Can you share some highlights of your projects?

    Jonko: yeah, my credentials are basically:

    1. Sailor Moon: La Luna Splende (DS) Translation

    Released: 2011 (game); 2021 (fan translation from Italian)

    RHDN translation entry here

    2. Suzumiya Haruhi no Chokuretsu (DS) Translation

    Released: 2009 (game); 2026 (fan translation completed)

    Japanese: 涼宮ハルヒの直列

    Original announcement post here

    In flight: other Haruhi games, next up is Heiretsu and Gekidou (wii games)

    3. “Serial Loops” – Chokuretsu Editing Suite

    Available for Windows, macOS (Intel and Apple Silicon) and Linux

    Project webpage here

    For a video explainer on how this editing suite was made, click here.

    In flight: Loopy Suite (hacking tools for the other Haruhi games)

    4. Into the Dream Spring (DS)

    Unannounced commercial DS homebrew game Jonko is developing with a friend (William278 of Breaking Bad DS fame) and a team of talented artists

    FFV Central: Awesome! Thank you for this overview and for the scoop on the unannounced homebrew game. We wish you all the best on these and future projects.

    So, what do you think? Have you played Jonko’s translations, and if so, which is your favorite? Comment below, or come check us out on Discord.

    This post has been viewed 20 time(s).