News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Trying to get into GBA ROM hacking, any directions for a newcomer?  (Read 3391 times)

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
What started out as me just going back to finish a GBA RPG, Lufia: The Ruins of Lore specifically, has turned into me first starting a graphics ripping project, then into delving into the game's code itself to try and document findings.

I only have mGBA to do the things I've been doing, and I heard it's not the best emulator for the job. I legit want to learn ASM just to hack this game, because fiddling with a memory editor and a hex editor aren't cutting it. Any pointers for how I could do anything? Like at all? Maybe emulator recommendations while we're at it?

There's one thing in specific I want to implement, that would be a nice way to start: The game has a Job system, with Job Points and all, the same system being used for Disc Monsters and their learnsets, but they're not visibly shown for whatever reason. I know where the value for JP earned is stored, in WRAM, at least for Disc Monsters. What I wanna do is make it so it's displayed after battle alongside EXP, and on the status screen as well.
Lufia afficionado, forum game player. Former SMW hacker.

[Unknown]

  • Jr. Member
  • **
  • Posts: 37
    • View Profile
    • PPSSPP
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #1 on: October 20, 2020, 11:02:55 pm »
I'd suggest using no$gba for its debugger.  That said, the perfect GBA debugging emulator doesn't exist, there are ups and downs.

For what you're looking to do, there are two ways I might approach this.  To start, I'd prep like this:

1. Get into battle with a known EXP value.

2. Create a save state near the end of battle, but before any final attack to end the battle.

3. Create a breakpoint for reading from the EXP value's memory address.

4. Note down the address of code that reads from that address until you see the value on screen.

5. Reload the save state, and try changing the value before each time, starting with the last time EXP is read from.  The goal is to find the address that reads the value to display it.  Hopefully, it's just once or twice.

6. Copy the entire function surrounding this address.  In most cases, this will be everything after a "bx ???" before the address until and including the next "bx ???".

7. At this point, I would break up and review the function to understand what it does.  This is the trickier part when you don't know asm yet, but it'll give you something to read and understand.

The function might do different things.  Hopefully, it just reads from memory and then draws to the screen by calling a function (using "bl".)  In the best case, you'll see a VRAM address or X and Y coordinates around that call, which will be where the EXP is being drawn.

If you get that far, the next thing I'd do - just to make sure the JP is what I expect - is replace the read of the EXP value with a read of the JP value.  This won't do what you want yet, but it'll be your first working change and help you confirm you are changing the right place.

-[Unknown]

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #2 on: October 21, 2020, 11:34:40 am »
Alright, got no$gba DEBUG version. Good lord, this is an intimidating emulator to learn. I have zero knowledge of ASM, so I'm essentially going the caveman route of going about things. I've been using mGBA to get the WRAM values I need in order to do things, since I can't do it as easily on no$gba, if I can best explain it. I can find where EXP and JP are stored in WRAM, but aside from that I have no idea how to work things out on no$gba. I'm writing notes in a text file on what I've found so far, so that I don't forget later.

So far this is what I've come to learn:

EWRAM 0203D1E0 = Eldin's current EXP (4 bytes)
EWRAM 0203D1E4 = Eldin's EXP until next level (4 bytes)
EWRAM 0203D20C = Eldin's current JP (4 bytes)

I have zero experience with anything as complex as this. SMW hacking has spoiled me beyond belief in terms of accessibility, what with it being more of a matter of compiling everything you want into one package rather than having to learn ASM, if the scope of the hack isn't too ambitious. With that in mind, I have no idea what any of those terms mean or what any of the instructions are supposed to lead me to do. Yeah, I'm pretty fresh meat in this area.

I wish I could make more sense, but I'm awful at explaining things in these contexts.
Spoiler:
As a side note, I hate being at the mercy of moderators having to approve my posts before they can show up. I'm way too used to other forums where there's no need for such a system.

October 21, 2020, 02:27:54 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Ugh, this whole thing is so frustrating. I keep jumping everywhere thanks to this stupid "cursor" the emulator comes with. I also can't search for hex values, just addresses. I wanna find stuff but I can't! I feel like I'm bashing my head against a wall.
« Last Edit: October 21, 2020, 02:27:54 pm by LucasRCD »
Lufia afficionado, forum game player. Former SMW hacker.

FAST6191

  • Hero Member
  • *****
  • Posts: 2966
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #3 on: October 21, 2020, 08:22:35 pm »
Adding things onto a screen is not impossible (pretty within scope of normal operations) but it is a fairly big reach for a first project even if it goes smoothly, get something fun (say a lack of memory) and it gets far harder. If it is the thing that will get you to stick with it then so it goes.

For assembly then for the GBA I like
http://www.coranac.com/tonc/text/asm.htm and of course http://problemkaputt.de/gbatek.htm

For assemblers I float between ARMIPS ( https://github.com/Kingcom/armips ) and cut down tools from GNU-GCC that come as part of devkitpro/devkitarm https://github.com/devkitPro/gba-examples

Afraid I don't really have a learning ARM assembly from scratch guide. Most sort of work their way up from fiddling with instructions. To that end I normally send people off to do some X86 for a bit and then come back as there are nice guides to that and assembly is similar enough that learn one and you can learn two, the third is then nothing special.
https://stuff.pypt.lt/ggt80x86a/asm1.htm is perhaps a bit light on the gentle introduction but it does keep most of it fairly on topic.
https://www.plantation-productions.com/Webster/ being what most looking to learn X86 assembly end up going in for.

For getting used to emulators then https://www.romhacking.net/documents/361/ covers basic tracing. If you can adapt that to whatever emulator you are using (do it in vba-sdl-h if you want but no$gba debug is where most will go these days) then you are in good stead.

Beyond that I have all sorts of fun links https://blog.quirk.es/2008/12/things-you-never-wanted-to-know-about.html
http://imrannazar.com/ARM-Opcode-Map
https://www.copetti.org/projects/consoles/game-boy-advance/
http://pineight.com/gba/managing-sprite-vram.txt
https://web.archive.org/web/20130826050933/http://drunkencoders.com/files/2013/03/unequivocal-answer.html
https://web.archive.org/web/20080309104350/http://etk.scener.org/?op=tutorial
https://heyrick.eu/assembler/

Looking around just now there are some intro to ARM things out there but it is more focused on things like the raspberry pi and mobile phone hardware which tends to be rather more advanced and less limited than the GBA (there is no divide function for instance, the GBA BIOS providing such a thing if you want it in hardware).


Anyway for doing stats readout on screen you can either subvert an existing readout (got a pointless luck stat or something? Change the text and change the read location to the stat you care about, should handle any hex-decimal conversions as well) or do your own, for which I would probably still use an existing one and tweak/replicate that -- follow along as it displays the normal level or whatever stuff but get it to then add your own copy of that which loads some different text (can do it in assembly if you want rather than adding another string, even if it is the sort of thing you will come to dislike devs for doing in future years), looks at the points you care about instead and finally places it on a free part of the screen.


Depending upon what you are doing if you are playing it in an emulator and there are some nice Lua functions you can instead get it to spit out the data to another window. Not as nice as something that will presumably work in any emulator or on hardware but something people go in for.

I do have a guide to GBA hacking http://www.romhacking.net/forum/index.php/topic,14708.0.html too.

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #4 on: October 21, 2020, 09:37:32 pm »
Okay, but where do I begin? I appreciate the replies and the amount of choices you're presenting me with, but this is terrifying if I can be perfectly honest. None of any of what you said says anything to me, and that's not to discredit any of you. That's entirely on me. All I really got from any of this were the first and last three paragraphs.

...I'm starting to wonder if I really am fit for ROM hacking. Maybe I'm biting off more than I can chew. Not like I can easily form a team to help with this either, so I'm entirely on my own to figure out something I've never delved into. I say I'm a former SMW hacker but I'm just a glorified pixel artist and level designer, I never wrote a single line of code on my own, ever.

Sorry for rambling, just me feeling a bunch of frustration from trying to figure things out on my own. I'm at least finding out about other unrelated things, such as where enemy stats are located in battle. With this last newfound knowledge, I can attempt to build a bestiary similar to that one Lufia II: Rise of the Sinistrals bestiary on that one GameFAQs guide.

As for finding where awarded EXP is located/stored in EWRAM, I think it's in 02038E7C? And there's also an extra calculation that awards extra EXP at the end of non-boss battles, the bonus being equal to total accumulated EXP divided by 5. The way this game handles things like that are just so weird, and I've already gone on long enough about unimportant things. Blah.

Incoming vent related to my experience so far, putting it behind spoilers so you don't have to be subjected to it forcibly:
Spoiler:
It's so weird how I say I want help yet I can't really do anything with the help that I get. It makes me feel useless and like I'm wasting people's time. I must be missing something that should be pretty obvious. And I'd rather not bother you or anyone else to write stuff for me and baby me around, yet it feels like I'll never get anywhere UNLESS something like that happens that way. I hate it.

What I thought would be something that'd be easy and fun to get into has turned out to be an exercise in frustration, trial and error, and clunky emulators that seem to fight against me whenever I try and do anything. This kinda extends to me and my stance on learning to code in general: "How long will I have to spend learning this? Will it even be worth it?" is something I always ask myself.

Sure I haven't even started to write a single line of code, and I'll never know how it truly feels or how hard it actually is until I try, but when reading through any of those links is already draining, the demotivation quickly settles in. I wish it didn't have to come down to me making such a big deal out of hacking and whining in public about it, but that's just how it is. This isn't anyone's fault but my own.

This is why none of my ideas and projects will ever take form. Unrealistic expectations and a lack of patience. And when I did try and make things a reality, they all crashed and burned because I ran into dead ends and got myself burnt out. If I can't learn anything instantly, I automatically deem myself a failure. Maybe this all stems from crippling laziness. Whatever the case is, I should really aim lower if I want to accomplish anything.
« Last Edit: October 21, 2020, 09:50:03 pm by LucasRCD »
Lufia afficionado, forum game player. Former SMW hacker.

[Unknown]

  • Jr. Member
  • **
  • Posts: 37
    • View Profile
    • PPSSPP
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #5 on: October 21, 2020, 10:49:58 pm »
Learning programming languages, including assembly, is a bit like learning a spoken language.  There's a big climb at the beginning where nothing makes sense.  Once you get past that, things start making sense a lot quicker.  The beginning steep climb often makes people worry they're not fit for it.

But I'm guessing you learned a spoken language from scratch using little more the gestures, pictures, and probably food.  It may have taken years, but now you're about as good with it as a native speaker of the language.  Anyone who can do such a thing is capable of the more trifling feat of reading and writing assembly.  But it's still hard.

Hacking is rewarding though.  It's painful at times, but the payoff is nice.  When it all comes together, it's pretty amazing.  But it pays to be passionate about what you're doing, because if you're meh about the result then the payoff won't be worth the road to get there.

Some more basic tips:
  • Assembly is the step-by-step instructions for how to do something, boiled down to math.  It seems weird at first, but it's all basic math.

  • It helps to understand memory, which it sounds like you do.  It's like a big checkerboard, with a little bit of information on every square.  Every square has a position on that board, which is the address.

  • You might try something even simpler, like making Eldin gain zero EXP or a fixed amount of EXP after each battle.

  • Code is organized into "functions" which help programmers stay sane.  These are building blocks that make bigger things happen, or sequences of those building blocks that make even bigger things happen.

For example, when you want to open a door you don't think about all the little steps of turning a door handle.  Instead, you first do something to guess at what type of door this is, then you follow a standard process to open that type of door.  Even when you used a new type of door handle the first time, you didn't think about the individual muscles to move or probably even where to put your fingers exactly.

Programs are just like that.  Someone wrote a function once to bend your thumb.  Later a totally different person wrote a function that grabs things, and it used that "bend thumb" function.  Yet another person's function grabs doorknobs in particular, leveraging that popular "grab" function.  Code is just a bunch of these functions.


To better explain some of my steps:

Quote
Create a breakpoint for reading from the EXP value's memory address.

https://problemkaputt.de/gbahlp.htm#breakpoints

If you press Ctrl-B, you'll get a dialog to create a breakpoint.  If the EXP is at 0x02038E7C, you'd put the following in for the breakpoint:

Code: [Select]
[02038E7C]!
This will make the emulator pause (it'll focus the debugger pane) whenever that address is written to.  You might see something like this:

Code: [Select]
ldr r1,=2038E7Ch
ldr r0,[r1]
adds r0,r0,4h
str r0,[r1]

I made the above code up, but let's break it down:

First, "ldr" means "load register".  It reads data from memory (the checkboard) into a register.  I tend to explain registers as things you're holding in your hands - but the computer is like an octopus, with many hands.

The GBA can't work with memory directly - it has to grab it into its hands first.  Once there, it can manipulate it, and later put it back on the checkerboard.  It may also help to think of memory as "farther away", like a refrigerator.

The first ldr is actually a shortcut to specify an address in a register.  The GBA can't really think about anything that isn't in a register, so even to read from an address - it first has to put that address into a register.

The second ldr in my example reads r0 from the address specified by r1.  So this would read the EXP value into r0.  The registers go from r0 to r15, although some registers have special purposes (like thumbs or feet.)  Usually r0 and r1 are the most readily accessible.

After that, my example adds 4 to r0.  It says r0 twice because the first r0 is where to remember the added sum, and the second r0 is what to sum.  For example, "adds r0,r1,r2" would add r1 and r2, and remember the result of that in r0.

Finally we have "str": store register.  This compliments ldr and puts a value onto the checkerboard that is memory.  So here, we're taking r0 (which is the original EXP + 4) and putting it back into the memory where EXP is normally kept.

In more common programming code, that example would be more like:

Code: [Select]
EXP += 4;
Assembly tends to be more verbose, because it's step by step.  These are the steps the CPU is really taking to do that.

The code you find will be more complicated.  For example, there's probably a base address where all party member information starts.  For easy example numbers, imagine it looks like this:

02038E00 - Eldin's information
02038E7C - Eldin's EXP
02038F00 - Torma's information
02038F7C - Torma's EXP

In this case, you might see code more like:

Code: [Select]
ldr r1,=2038E00h
lsl r2,r0,8
adds r1,r1,r2
ldr r0,[r1,7Ch]
adds r0,r0,4
str r0,[r1,7Ch]

Some new things here again.  The first ldr is familiar, but now it's the base address of the first character's information.

Next, we have "lsl" which is new.  This stands for "Logical shift left".  This is possibly the most complex math you'll see in GBA assembly.  A shift is a multiply by a power of two.  In this case, it's shifting r0 left by 8.  In other words, it's multiplying r0 by 2 to the power of 8.  For a computer, this is VERY EASY math (like multiplying 5 by 100 would be for you), so such a multiply is common.

It's called "logical" because of how negative numbers are handled, but don't worry about that detail for now.

So, why would it do this?  In my theoretical scenario, the original "r0" is which character should gain 4 EXP.  So if it's 0, it'd be Eldin... if it's 1, Torma... and so on.  And my example was that each character's information is 0x100 apart (which is 0x001 shifted left 8 ), so we're just figuring out how much to add to get to the right character.

Next we add, that's pretty straight forward.

Finally we see a new trick from ldr.  Instead of [r1], we see [r1,7Ch].  If you remember, my example has the player info at 00 and the EXP at 7C.  This simply says to read from "r1 + 0x7C".  When you say [r1], it actually means "r1 + 0".  The extra number is called the "offset".

After that, my example should follow from the last example.



This is just an example, though.  I didn't look at the game's actual code.  There are many other things it could do.  Obviously, it doesn't always add 4 EXP after a battle, and it probably needs to divide what it would add by 5 to give the bonus.  But it follows the same building blocks: loading into registers, doing things with them, then putting them back.

-[Unknown]
« Last Edit: October 23, 2020, 02:37:57 am by [Unknown] »

Risae

  • Jr. Member
  • **
  • Posts: 73
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #6 on: October 22, 2020, 03:36:57 am »
Just want to drop this in, might be helpful:

https://gamehacking.academy/lesson/1

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #7 on: October 22, 2020, 08:45:02 am »
So here's something interesting that I found. By adding a breakpoint to 02038E7C, the memory address that gets added to in order to hand out the total EXP at the end of battle, this happens. If I do another battle, the same result happens again, but with a 44 instead of a 54 at the end. After that, the amount of EXP handed out at the end of battle goes back to normal for whatever reason. So maybe the rabbit hole goes a bit deeper than I thought.

I think what's been frustrating me is the fact that I'm trying to do everything at once when I should be focusing on one thing. The thing I understand the most so far is how the game handles monster stats, including the fact that there's a lot of data redundancy (seriously, some  stats are listed 3 times, yet only the last instance is what's read and altered. It's almost like they did this on purpose to prevent people like me from finding out how things work).

So if the JP thing doesn't work out, I'll instead just go and write a comprehensive bestiary similar to Iron Knuckle's bestiary included on their GameFAQs guide, which was done in a similar fashion, by diving right into the game's code. Granted I have a lot of work to do, what with the absurd amount of enemies and the fact that I'd have to locate where the original stats are lifted from and where the moves are located.

October 22, 2020, 09:00:20 am - (Auto Merged - Double Posts are not allowed before 7 days.)
I should probably include more screenshots in general. Here is a screenshot of no$gba and the two values I added breakpoints to, those being the value for EXP and Gold handed out at the end of battle respectively. I can see some things of interest but I don't know how to read them, or where I should be looking for or at.
« Last Edit: October 22, 2020, 09:00:20 am by LucasRCD »
Lufia afficionado, forum game player. Former SMW hacker.

FAST6191

  • Hero Member
  • *****
  • Posts: 2966
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #8 on: October 22, 2020, 09:36:05 am »
Assembly is the final step for most people in ROM hacking, and they may already know some coding to reference against (compared to say Python, which is a very high level language compared to the bare metal of assembly, in assembly you handle everything rather than having it abstracted away but it is all still covering much the same concept -- loops is loops, data is what you define it as, you might not have to consider where it lands in memory in anything but assembly but you still have to declare it so something can figure out where to stuff it...).

Prior to that they will tend to have messed around with text and what it entails, graphics and what they entail, depending upon the system (most GBA games being of the easier to do variety compared to the SNES), maybe messed around with some level design, done some cheats and then started relating it all back to things, possibly starting by hardcoding a cheat. Hardcoding a cheat then say means you find a conventional infinite health cheat (search, lose health, search, lose health, stay at health and search for things that remained the same, maybe use a potion and see what went up...) before instead of making a cheat setting a breakpoint for anything to write that area. You then change this so instead of subtracting it does nothing and you have at least the first stage of a cheat*.

*for this I normally use Mario as an example. Lives can be lost by poison mushrooms, enemies, pits, hazards, getting crushed, running out of time and a few other things most likely. Each of these might well be something that twiddles the lives counter vs a simple memory cheat that ensures it is always at a value. That said you can also just make something that runs every frame (see vblank for the most common approach here) and sets the lives counter to 99 or whatever you want.

Hardcoding a cheat then maybe sees them think ah I could do a shift here and effectively make double exp and thus change balance, or maybe completely nerf a mechanic and potentially change the game (how many games would change radically if you removed the timer or removed randomness?). If an enemy say wants to be double speed you might find where its OAM data is found (it has to display on the screen after all, assuming this is a platform/action type game anyway, speed in final fantasy then tending to be more stats) and then look at what changes that, somewhere along the line will be the AI controlling it and you can do all sorts of things to alter its movement. If you fiddled with OAM you can probably then also fiddle with text to make yourself a nice variable width font hack, or change the location of text on a screen, and maybe also trace it back so you can find the font and learn how the game interprets it.
At this point you would probably be able to do the stuff above where you replicate the text grabbing feature or say the EXP, make sure the game executes your new code (every time the screen gets generated it will have a list of things to do, adding to this list is seldom too difficult unless you are on an instruction budget), tweaking the grabbing feature to both look at the thing you care about and putting it in another location on the screen, all before returning control to the base game. It is not a radical hack -- the game already reads text all the time (predictably at that so you can intercept it easily -- it will have to read the exp value to display it on screen, now you know where it lands) and a few dozen bytes extra is not a big ask in most scenarios. It is however fairly ambitious if you are going in completely cold/new, though within reason for a learning hack (any programming teacher, or indeed any teacher of practical skills, worth their salt will tell you a project that the student is motivated to stick with is 10 times better than an something abstract and boring that they have to breathe down their neck to complete).

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #9 on: October 22, 2020, 10:29:45 am »
It is however fairly ambitious if you are going in completely cold/new, though within reason for a learning hack (any programming teacher, or indeed any teacher of practical skills, worth their salt will tell you a project that the student is motivated to stick with is 10 times better than an something abstract and boring that they have to breathe down their neck to complete).
Yeah, that's a bit of a problem I have. I tend to go immediately ambitious when trying out new things. I thought this was gonna be a simple task, boy how wrong I was. I am learning some interesting facts about the inner workings of the game. Who knows, maybe within an extended period of time I can even work out how the speed-based not-quite-turn-based battle system works.

What I wanna know is what each of the columns that are displayed on no$gba's top left part mean, respectively. I know the first two are the address and the value it currently has, respectively, but everything else appears to be a blank to me. I keep being told that I need to note things and find where the EXP value is read from. Problem is, I don't even know what I need to do to locate it. Locate what writes into the address, I mean, for lack of a better terminology. Maybe I'm misusing terms, I don't freaking know the proper terms for this. Where do I click? What do I click? Sometimes I click on the breakpoint'd addresses and they boot me to a random part of the code. All this jumping around really isn't helpful and is more of a nuisance than anything.

October 22, 2020, 05:12:15 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Hmm, considering I've been going rather off-topic and all over the place with this thread, I figure I should create a new thread focusing specifically on discussing Lufia: The Ruins of Lore stuff and my journey to try and understand things. I'm not sure if this sort of thing is frowned upon in here, so I'll just wait for some "okay" on this front.
« Last Edit: October 22, 2020, 05:13:40 pm by LucasRCD »
Lufia afficionado, forum game player. Former SMW hacker.

[Unknown]

  • Jr. Member
  • **
  • Posts: 37
    • View Profile
    • PPSSPP
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #10 on: October 23, 2020, 02:59:49 am »
I should probably include more screenshots in general. Here is a screenshot of no$gba and the two values I added breakpoints to, those being the value for EXP and Gold handed out at the end of battle respectively. I can see some things of interest but I don't know how to read them, or where I should be looking for or at.

Ah, okay.  Here's what's happening: there are different types of breakpoints, and you're using the wrong kind.

A "breakpoint" is just something that stops the CPU from executing instructions when something happens.

The basic type of breakpoint is one that stops the CPU when it reaches an address.  For example, 08123456 might represent some game code.  If you set a breakpoint there, the CPU would stop when it's about to execute that code.

That type is very useful, but it requires knowing about the code.  It's kinda like solving the formula "x = y * 2" when you know the value of x.

Here we don't know the code - it's what we're trying to find.  Instead, we know the memory address - we know y.  The reason things have gone wrong is that you accidentally put the value of y in for x, so you ended up solving the formula wrong.

What we want is a "memory breakpoint".  Memory breakpoints stop the CPU when *any* code accesses a certain memory address to load or store data.  To use this sort of breakpoint, no$gba requires a different syntax: "[02038E7C]?".  If you just put 02038E7C, you'll set an execution breakpoint, the wrong kind.

How do I know this?  Simple.  The way execution breakpoints are implemented in most debuggers, including no$gba, is by *replacing* the code you set a breakpoint for.  So when you set an execution breakpoint at 02038E7C, it replaced the value there (the EXP) with assembly to tell the CPU to stop.  But... it's not code, it's EXP.  So EXP became a crazy number.

Like "lsl" and "ldr", etc. there's an instruction "bkpt" which causes the CPU to stall for debugging.  That's what an execution breakpoint uses.

If you try it using the brackets, things should go smoother.

What I wanna know is what each of the columns that are displayed on no$gba's top left part mean, respectively.

Well, they only make sense if you look at code.  In your screenshots, you're looking at data with them, so it's just a bunch of nonsense right now.  When you hit a memory breakpoint you should be looking at some actual code.

The first column is the address you're looking at.  You know that, but to explain: just like data (such as an EXP value), code is also found at addresses.  At the end of the day, the computer thinks of "adds r0,r1,r2" as a bunch of numbers just like everything else.  An address in memory can hold code or data, just like a box can hold food or dirty laundry.

The next column is the number at that address, yes.  Most GBA code is "Thumb", which is always 16 bits.  So when you're looking at real code, chances are you'll just see 4 hexadecimal digits in this column.  When you see 8, you're either looking at data or ARM code (less commonly used on the GBA.)

And yes, the designers or "ARM" and "Thumb" intentionally used those names as a play on words.  Thumb is meant to be a much smaller, simpler, but still versatile subset of ARM.  Get it?

Next up you have what's called the mnemonic.  This is the "name" of the instruction.  adds, subs, ldr, etc.

Then you have the operands.  These are the values used by the instruction - in my example of "adds r0, r1, r2" the operands are r0,r1,r2.  We know that the "adds" mnemonic would add operand #2 and operand #3, and store the result in operand #1.  In other words, "r0 = r1 + r2".

The next column after the semicolon is the number of cycles this instruction takes.  The GBA was 16.78 MHz, which means it has 16780000 cycles every second.  If you see ";2" in the second to last column, it means that instruction takes 2 of those cycles.

The final column is a simple sum of the cycles from the top of the screen (it's more useful when you export to a file.)  This tries to give you an idea of how overall expensive your code is.  If you wrote 100 lines of assembly, it's less important how long a single line takes, and more important how long the entire sequence takes.

Locate what writes into the address, I mean, for lack of a better terminology. Maybe I'm misusing terms, I don't freaking know the proper terms for this. Where do I click? What do I click? Sometimes I click on the breakpoint'd addresses and they boot me to a random part of the code. All this jumping around really isn't helpful and is more of a nuisance than anything.

If you press Ctrl-B, you can set a breakpoint.  Double clicking in the top left will also set a breakpoint (but it's not normal double clicking - just clicking twice, even slowly, will do it.  I did say not perfect, right?)  Pressing left and right arrow keys will do things I haven't explained yet, so avoid doing that for now.  It's pretty useful but will be bewildering at the moment.

When you have a breakpoint set (bottom left part of the screen), double clicking on it will go to the address it's set at.  It's taking you to weird places because of the issue I explained earlier about execution vs memory breakpoints.

Quote
Hmm, considering I've been going rather off-topic and all over the place with this thread, I figure I should create a new thread focusing specifically on discussing Lufia: The Ruins of Lore stuff and my journey to try and understand things. I'm not sure if this sort of thing is frowned upon in here, so I'll just wait for some "okay" on this front.

I don't see why that would be frowned upon, though I haven't posted a ton here myself.  Maybe notes might also find their way into the wiki:
https://datacrystal.romhacking.net/

-[Unknown]

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #11 on: October 23, 2020, 09:36:51 am »
What we want is a "memory breakpoint".  Memory breakpoints stop the CPU when *any* code accesses a certain memory address to load or store data.  To use this sort of breakpoint, no$gba requires a different syntax: "[02038E7C]?".  If you just put 02038E7C, you'll set an execution breakpoint, the wrong kind.
Ah, no wonder I was having so much trouble, I didn't know about the existence of two different types of breakpoints! Maybe it's documented within no$gba's intruction manual, but considering the sheer size of it, can you blame me for not finding it?

Thank you so much for telling me that, you have no idea how much you have helped.
Lufia afficionado, forum game player. Former SMW hacker.

phonymike

  • Jr. Member
  • **
  • Posts: 40
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #12 on: October 27, 2020, 03:53:41 am »
Once you figure out where the value in RAM is, you'll want to take that value from RAM and display it as a BG tile, so you're going to want to know where the BG map data is stored and how to change it. BG map data can be placed at different places in RAM, and you can use no$gba's Vram Viewer to see the BG maps 0, 1, 2, and 3. It will show you the actual map address, like 6001036 for example. Addresses for the GBA that start with 6xxxxxx are VRAM addresses. Memory that's used to display data on the screen. If the variable that you want to display is from 02038E7C, memory at 2xxxxxx is WRAM (Work RAM) also general purpose RAM. So you'd need to read data from 02038E7C and copy it to 6001036 for example. These are probably not the exact memory addresses but that's for you to figure out.

Using the example assembly code from [Unknown] (because my gba assembly is rusty), your code might look something like this
Code: [Select]
ldr r1,=2038E7Ch ;load address of variable into r1
ldr r0,[r1] ;load what's at address r1, put it into r0
ldr r1,=6001036 ;load address of map spot for new tile into r1
str r0,[r1] ;store value from r0 to address in r1

It looks like you can use xkas-plus v14+1 to assemble the commands and insert into the ROM pretty easy. Locations starting with 8xxxxxx are ROM cartridge locations and that's where your hack will be stored.

You'll also need to insert a jump into the game's code. This will interrupt the code, make it execute your code, and then return to the game code.

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #13 on: October 27, 2020, 09:57:42 pm »
Oh man, that's an even better amount of help! I can't believe I overlooked the replies to this thread, I'll see what I can do with that. I know about the existence of jumps in code. I believe I can just do "JMP $[insert address here]" and it'll work? Now the question is, where would I insert the jump?
Lufia afficionado, forum game player. Former SMW hacker.

FAST6191

  • Hero Member
  • *****
  • Posts: 2966
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #14 on: October 28, 2020, 12:44:41 pm »
Where to insert depends upon what you are doing and what the program is doing.

If you have to overwrite something to do it (not usually much blank space in the normal program flow after all) then if you can pick something that does not matter, and after it has done things you need it to do. Otherwise you get to replicate the effects of whatever you just overwrote.
If the jump is there to force the outcome of a decision the game makes then best to do that before the undesired outcome gets taken. This need not be before a compare is made or any calculations done to prepare for the compare function. Instead it can do all the compares it wants but if the break if not equal is never take or is changed to always jump (or whatever combination of that you need for your purposes) then the end result will still be what you want. In an ideal world you would free up a bunch of instructions/space by reclaiming any space and negating any instructions but for practical results then in 99% of cases you would need specialist equipment to measure differences or step through in a debugger by hand of allowing it to do the compare and jumping at the first available opportunity. The 1% usually being things where the game is broken and those few cycles actually make a difference or maybe for handhelds then sometimes it might allow it to get to a rest state quicker to lower power consumption (we have seen a few power reduction patches https://www.dwedit.org/dwedit_board/viewtopic.php?id=480 ).

If we are still carrying on with the show battle stuff then I would probably look to find the loop that handles giving things to the draw command (if it is a separate function it just says put this text at this location) or the draw aspect in general if it is bundled in and before it hands control back to the game. There are other places you could use as it is possible to do something like check to see if you are in battle end screen -- there is bound to be some area of memory (or combination of a couple) that is only a certain value when in that screen and no other and thus you could tack on a write this value to the screen in this location type setup to a basic vblank.

For the GBA you will probably also want to figure out what mode the processor is in and what mode the code you are jumping to is in (and whether it has any mode switches when it gets there). Depending upon what is done you might also want to figure out a return location to make sure it does not jump back to where you started/started + 1 instruction and then undo all you might have just done.

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #15 on: October 28, 2020, 06:18:31 pm »
I've finally decided to check VRAM to see how battle text is rendered. Turns out it's all stored in BG 0, Text Mode (image 1,image 2).

I basically did two battles: One with low level enemies (enough EXP to level up but not gain enough JP to learn any skills, pictured earlier), and one with endgame enemies (earning enough JP to learn 3 skills at once. Image 1, image 2. The first two images were from battle 1, the last two are from battle 2, in case it's not clear).

I still haven't fiddled around with xkas or patching yet because I don't trust myself to do this without screwing up. I'll likely build some confidence once I end up getting a firm enough grasp of this stuff. Hopefully what I've provided in this post can be informative enough for you guys to help me?
Lufia afficionado, forum game player. Former SMW hacker.

FAST6191

  • Hero Member
  • *****
  • Posts: 2966
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #16 on: October 28, 2020, 10:24:10 pm »
"I don't trust myself to do this without screwing up"
You will screw up.
This however is why we have copy and paste and one of the reasons ROM hacking is rather nicer than welding, drilling holes and what have you where failures might teach you something but still cost for the materials to do it.

Or if you prefer I, being one that reads the links I provided earlier for fun and otherwise do all I do, will also screw up and break something were I attempt this hack. Might be in a different way ( https://textexpander.com/blog/the-7-most-common-types-of-errors-in-programming-and-how-to-avoid-them/ ) but crashing, errors and failure all the same. I will wager good money that anybody else in this thread or on the forums that might also be playing at high levels will tell you the same thing.
I might in turn be able to spot the error and fix it quicker but still get to fix something.

[Unknown]

  • Jr. Member
  • **
  • Posts: 37
    • View Profile
    • PPSSPP
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #17 on: October 28, 2020, 11:30:39 pm »
In GBA assembly, it's not JMP but instead b (stands for "branch" which in assembly speak means to go somewhere else.)

Importantly, there are conditional branches, like beq and bne (Branch Equal and Branch Not Equal.)  These are usually used for comparisons, but you'll want to read about "flags" to understand these.  Here's a sample though - consider this code:

Code: [Select]
cmp r1,r2
beq 8123456h

Here we have cmp - Compare, and then a beq which goes to 8123456h if r1 and r2 were the same value.  We could have blt (Branch Less Than) or bge (Branch Greater or Equal), and several others.  All based on the comparions of r1 and r2.

However, it doesn't have to be cmp.  "cmp r1,r2" is actually "subs IGNORE,r1,r2".  beq actually jumps if the result was zero.  blt jumps if the result was less than 0, etc.  That means you could do:

Code: [Select]
subs r0,r1,r2
beq 8123456h

It'd be the same, but you could use the subtracted value (r0) later.  Most of the time, you'll see GBA compilers (which were terrible at optimizing) use cmp, but sometimes they will do something almost smart and skip it.

GBA assembly can also be tricky with jumps.  You'll see a few forms of jumps:

> adds r0,=8123456h
> mov r15,r0

The first part sets r0 to an address of the code to jump to.  The second part is the actual jump, but it doesn't look like one.  r15 is the "program counter".  It's a special register that holds the memory address of the code that's about to be loaded into the CPU to execute.

Because of that, setting r15 to any value is a way to jump to that place.

> bx r14

This is a jump.  In this example, it's jumping to the value of r14.  It seems like the same as "mov r15,r14", but there's a slight difference: bx stands for "Branch and Exchange".  It's used to *potentially* switch between ARM and Thumb.  Most of the time, it'll just stay in Thumb, though.

"bx r14" is particularly special.  r14 is another special register, which I'll explain below.

> bl 8123456h

This is "Branch and Link".  If "b" and "beq" are like taking off in the wilderness, "bl" is like sticking a flag in the ground and making sure it's visible before running off.  The "link" part means it sets r14 to the address after the bl (i.e. to r15, basically.)

You use this to "call a function".  I explained code is organized into functions before.  After that function "returns" (is finished), the CPU will go back to the next instruction after the r14.

It does this by using "bx r14" (often), "mov r15,r14", or sometimes "pop r15".  These are the typical ways a function says it's done, and they all put whatever was originally in r14 back into r15.



When adding your own code, it's common to find some empty space in the ROM, put your code there, and then jump there.  You'll need to "trampoline" there, which likely means loading the address into a register and the "mov r15,r0".

All the ways of jumping have a "maximum range".  If you put your new code near the end of the ROM (I suspect free space starts at 0x087E8228), it'll be too far to jump directly - you can't just put "b 87E8228h".

If you find yourself eventually enjoying assembly, another tactic (my preference) is to rewrite some largish function that the compiler did a horrible job at, replacing it with a smaller and better version.  Then you have space to start adding things.  But I guess most people see it the other way around:
https://www.reddit.com/r/ProgrammerHumor/comments/jils5x/the_strongest_of_all/

I'd recommend armips over xkas, personally.  I'm biased though, because I've contributed to armips.

-[Unknown]

LucasRCD

  • Jr. Member
  • **
  • Posts: 23
  • Avatar by @ImmatureWaffles on Twitter
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #18 on: October 29, 2020, 08:12:12 am »
The funny part is that as a former SMW hacker, xkas has actually been obsoleted and replaced as the primary patcher/assembler tool for that game. A new one called asar does everything it does but better, and easier. So it's probably a safe assumption that armips is the better of the two.

One thing I've been thinking of is to empty out certain parts of the ROM. The game has Link Cable functionality, with a Disc Monster trading system between copies and a cooperative(?) version of the Ancient Cave dungeon. I doubt anyone nowadays would see much use in either of those. Theoretically, getting rid of it all could free up some space, including space for any kind of new text. I assume that just zeroing the parts of the ROM like that would be the easiest solution, even if it's not really elegant?

I'd comment on anything else but I can't do it at the moment; I'll attach more parts to this post when I come back.
Lufia afficionado, forum game player. Former SMW hacker.

FAST6191

  • Hero Member
  • *****
  • Posts: 2966
    • View Profile
Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
« Reply #19 on: October 29, 2020, 09:46:17 am »
Expanding GBA ROMS is trivial.
Every single GBA ROM can access the full 08000000 though 09FFFFFF region (plus mirrors) which amounts to 32 megabytes. Some homebrew, flash carts and Shrek https://mgba.io/2015/10/20/dumping-the-undumped/ can exceed this but let us not go there.
There is no size or cart type indicator in the header. Just use the space and change any relevant pointers accordingly. As Lufia GBA is 64 Mbit/8 megabytes to begin with then you have loads of space. If you don't have to go above 16 megs then don't as various flash carts will thank you for that one, likewise it is not always best to slam it right to the last bytes of the ROM as some do appreciate being able to trim and other patches might use that space for cheat support or something.

Even those games that are 32 megs in nominal size (or 256 mbit if you are using flash cart parlance) still tend to have megabytes and megabytes of space available. Mother 3 and maybe the GBA videos being the exceptions in this one. Again though the whole untrimmed Lufia GBA ROM is 8 megs, not sure what it is trimmed.

"I doubt anyone nowadays would see much use in either of those."
That you can not assume, both in general (if nothing else I still get asked for the occasional multiplayer patch if a flash cart is acting up and existing ones still get downloads) and going into the future (oh no android based emulator got bluetooth support for the link cable setup).