Romhacking.net

Romhacking => ROM Hacking Discussion => Topic started by: LucasRCD on October 19, 2020, 01:17:28 pm

Title: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 19, 2020, 01:17:28 pm
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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] 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]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] 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:

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]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: Risae on October 22, 2020, 03:36:57 am
Just want to drop this in, might be helpful:

https://gamehacking.academy/lesson/1
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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 (https://cdn.discordapp.com/attachments/461384755079020584/768810446853505034/unknown.png) 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 (https://cdn.discordapp.com/attachments/461384755079020584/768820148533854208/unknown.png) 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 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).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] on October 23, 2020, 02:59:49 am
I should probably include more screenshots in general. Here (https://cdn.discordapp.com/attachments/461384755079020584/768820148533854208/unknown.png) 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]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: phonymike 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 (https://github.com/devinacker/xkas-plus/releases/tag/v14%2B1) 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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?
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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 (https://cdn.discordapp.com/attachments/769286995779780689/771094085325946880/unknown.png),image 2) (https://cdn.discordapp.com/attachments/769286995779780689/771094282626400276/unknown.png).

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 (https://cdn.discordapp.com/attachments/769286995779780689/771097259239931934/unknown.png), image 2 (https://cdn.discordapp.com/attachments/769286995779780689/771097781523447808/unknown.png). 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?
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] 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]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD 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.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 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).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 29, 2020, 10:03:38 am
Alright, I'm back. I actually forgot to do the whole breakpoint thing with the JP meter. I need to ask something before do so, and I can't believe I haven't asked this earlier: What is the second address mean at the bottom right screen? (https://cdn.discordapp.com/attachments/769286995779780689/771367803067432970/unknown.png) What is that bottom right screen? I may need to revise the way I document things if it turns out I've been misinterpreting what it means.

Also, ninja'd, so I'm gonna add more to this post than I originally intended to.

"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).

Fair point, I just came to that conclusion because expanding the ROM itself didn't cross my mind, mostly because I have no clue how I would do that. It's probably really simple to expand it to 16 MB, but in order to make any proper use of the new space, I'd need to do a bunch of things that are beyond my current level of knowledge. A daunting task, indeed. No idea what you mean by "trimming" a ROM. Wouldn't that require recompiling the ROM, thus necessitating a disassembly of the game?
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] on October 29, 2020, 10:57:43 am
Alright, I'm back. I actually forgot to do the whole breakpoint thing with the JP meter. I need to ask something before do so, and I can't believe I haven't asked this earlier: What is the second address mean at the bottom right screen? (https://cdn.discordapp.com/attachments/769286995779780689/771367803067432970/unknown.png) What is that bottom right screen? I may need to revise the way I document things if it turns out I've been misinterpreting what it means.

This is what's called the "stack".

As I'd mentioned, there are 16 registers - hands of the octopus.  And memory is where things go when you don't need them in your hand right now.  Stack is just memory, but it's a "special" kind of memory just by convention.  There's nothing actually special about it, except the way game code uses it.

Everything I'm talking about now is a "convention".  I mention this because a programmer can do whatever they want.  If some developer working on Lufia decided to hand-write some assembly for an important function of the game, they could've not followed these conventions at all.  But for 95%+ of code, they'll be followed.

So, imagine a function call.  Let's take something simple, like "a = pow(b, c)".  This function takes b to the power of c, and returns it in a.  There's no single instruction for it (like "pow r0, r1, r2"), it requires a bunch of instructions.

The assembly for pow() would be "bl 8123456h" (address is an example.)

But, how does it know which things to multiply and where to put the result?  Convention.

We call the inputs to a function "arguments" or "parameters".  They should be r0, r1, r2, and r3.  In this case, there are only two, so r0 and r1.  If there are more than 4, it uses the stack but don't worry about this for now.

The result is then returned in r0.  So now we know pow() would look like this:

Code: [Select]
mov r0,b
mov r1,c
bl pow
mov a,r0

But, what if you had something important in r0 already?  Or what if you had important things in other registers?  This is just a jump, really, a "Branch and Link".  If pow makes a bunch of changes to registers, you'll lose their values.

This is where the stack comes in.  You save the registers you care about on the stack.  Here's the convention:

r0-r3: Arguments / return values.
r4-r11: "Callee saved".  Callee means the function itself.  If pow() wants to use these registers, it must make sure it saves them and puts them back the way it found them.

r12: "Callee saved".  This is a special temporary register.
r13: Stack pointer.  This is the address of the stack (more on that in a bit.)
r14: Link register, technically callee saved.  This is the calling code to return to.
r15: Program counter.  Code address to execute soon.

Let's say pow is complicated.  You might see this code in it:

Code: [Select]
push r4-r7,r14

... code for pow(r0, positive r1) and pow(r0, negative r1) ...

pop r4-r7,r15

In many ways, "push" is like str.  In fact, it's technically stm (store multiple.)  It does the following:

 * Decreases the value of sp (aka r13) by enough for the registers passed.  In this case, 20 bytes.
 * Supports ranges for r0-r7 only, and can specially do r14.  If you want to push r8, you'd move it to another register first.
 * Stores each register in that space, i.e. "str r4,[sp,0]" and "str r14,[sp,16]".

The pop instruction is similar, in reverse.  It's like ldr, where it reads from the stack.

So now finally to your screenshot:
https://cdn.discordapp.com/attachments/769286995779780689/771367803067432970/unknown.png

03007C00 is the current value of sp.  It started as a higher value, and goes downward as more functions are called, then back upward when they return.

If you notice 03007C28 says "Pushed r7".  That means this was stored by "push r7", or actually a "push r4-r7" if you look further down.  The extra r5, r6, r7 are probably actually r8-r10 moved to those registers.  This is very common.

The "Return from Lxx_8001a5Ch" is the r14 pushed on the stack.

"Allocated" means that the stack value was changed without using push.  For example:

Code: [Select]
push r4-r7,r14
mov r4,r8
mov r5,r9
mov r6,r10
push r4-r6
sub sp,sp,16

You would do this if you needed a quick "scratchpad" to save registers while running numbers.  Maybe your math formula is complicated, and using all of r0-r10 (11 registers) isn't enough.  So you scribble some things down into that allocated memory, temporarily.

Very important things to understand about stack:

 * It's temporary.  As soon as pow() is done, another function will use these addresses and overwrite it.
 * The address might change.  pow() might be called by different people - some might allocate more or less stack.  So the addresses pow() sees for sp are not consistent.

The second column there, like on the left, is the value stored at that address.  I'm really burying the lead here, but the above is important context for this fact.

If you see an important/useful value on the bottom right, the address is still not safe to say "this is where the game stores JP".  Even a hack you apply to another function might change that address.  It's just a temporary scratch location.

Fair point, I just came to that conclusion because expanding the ROM itself didn't cross my mind, mostly because I have no clue how I would do that. It's probably really simple to expand it to 16 MB, but in order to make any proper use of the new space, I'd need to do a bunch of things that are beyond my current level of knowledge. A daunting task, indeed. No idea what you mean by "trimming" a ROM. Wouldn't that require recompiling the ROM, thus necessitating a disassembly of the game?

You can basically just make the file larger, like using a hex editor or with ".org" in armips.
https://github.com/Kingcom/armips#set-the-output-position

-[Unknown]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 on October 29, 2020, 11:15:14 am
Trimming a ROM is something many flash cart users will do.

Generally speaking chips to store things on at the time at least came in power of 2 size progression (1,2,4,8,16,32,64....) and ROM dumpers would dump the whole lot. The game itself is not obligated to take up that full amount though so you can then take off the end part (trim it off if you will) and go from there. There is no value in the header but 99.999% of games will be either 00 or FF so a trimmer will work backwards to the first thing that is not 00/FF and chop it from there. It can cause problems in some cases (00 and FF are both valid things to put in a ROM, one of the Teenage Mutant Ninja Turtles being one of the examples if someone wants one) so some will skip ahead a few hundred bytes just in case.
Anyway trimming one game might get you something (we have had a few games be 256Mbit titles but only use about 140) but it is more that doing it for 30 or so to load a flash cart with gains you enough space to fit another game or two on. Today yeah SDHC means you can probably roll around with the entire ROM set, emulator set for everything the GBA emulates, all the homebrew and all the ROM hacks whilst still having room left over (depending upon how much you use the video and music homebrew anyway) but that is not everybody and even those that do have SDHC still appreciate a smaller ROM in some instances (there are often fast internal memory sections).

Now if you wanted to do a ROM rip wherein junk, or "junk", files were taken out of the ROM to reduce size (seen on many PC games, original xbox games, some Wii stuff, the DS and some other things besides) then yeah as the GBA is without a file system (unlike everything on that list in the previous bracketed section) that would be a nightmare project unless it so happens the junk is on the end of the ROM. A full decompilation (such that it ever could be on a GBA -- plenty of in line assembly on the GBA) is probably a bit excessive but would work.

As for difficulty in expansion.
Make blank file full of 00 of suitable size.
Add blank file to end of ROM. Copy and paste with a hex editor maybe, though the command line "copy /b file1.gba+blankfile.file expandedrom.gba" is what I normally use.

If you opted for the "meh I will just make a 32 meg 00 filled file and chop it back down afterwards" then chop it back down to your chosen size.

Again there are no header values, no ROM type/mapper/mbc/pages/... to change or expect fallout from. Add the space and it is there to use on any ROM you like.
You don't need to do anything you were not already doing -- pointers and maths on them work just the same*, jumps in the assembly work just the same, all internal functions as far as DMA/BIOS/SWI and memory copying work just the same...


*depending upon what guide you read then you might have read something like "all GBA ROM pointers start with 08" which is a decent enough rule of thumb (few things use the different waitstate mirrors, and most ROMs are 16 megabytes or less and thus contained within 08000000 through 08FFFFFF and thus don't need the 09 range or equivalent higher mirrors), indeed I will often search for 08 and if I see a whole sea of them mostly some set distance apart (08080808 is a valid address after all, indeed more likely than many odd ones) then I will take a look as I probably just found a pointer table which usually contains something good (even if only to eliminate from the search for something else -- if you found the music and graphics pointers then you can eliminate those regions from your text search).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 29, 2020, 01:15:14 pm
Hmm, so basically that second column isn't the part of the ROM it's pulling the information from? I've noticed before that EXP and Gold gains end up calling one thing in common, before going about the rest of their functions. I'll see if I can find some stray free space within the ROM, otherwise I'll have to do some ROM witchcraft to achieve the extra space (it at least sounds like it to me, but it's probably more a matter of patience than anything). Maybe my best hope for this would be to put up a "help wanted" post, in the worst case scenario.

On a tangential note, I just realized how much of a mess my virtual work space. I ended up accidentally making the unmodified ROM of the game blank. I should store these altered ROMs somewhere else.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 on October 29, 2020, 01:49:27 pm
You are seemingly grasping the fundamentals of assembly and program flow in that yet expansion seems hard? That is bizarre to me.

It really is a matter of add extra data to the end of the ROM containing all 00 hex. Best to have it line up with the 4,8,16 or 32 megabyte mark if aiming for that professional look and it tops out at 32 for most purposes. No size values nor end of file limits in any kind of header or ROM description to worry about (such a thing is actually one of the harder parts when it comes to dumping GBA games as you then have to figure out how big it should be).

In older systems it is potentially a pain as you have to deal with sections being switched in and out at will of the game such that you can never be sure it is there, or have to swap out, or have to make room in the area you want it in (which may be easier said than done if the devs used it all).
In the GBA the entire ROM is present in the memory at all points and suffers no penalty from jumping from something in the first two megs to the last two from one instruction to the next.
If you can change pointers to house your next code/graphics/music/text/whatever alteration in some reclaimed space, or simply to fix it if you altered lengths of text strings, then it is the exact same logic with the space you added to the ROM (find new location in the ROM you are using/want to use, add location value to 08000000h, this is your pointer, overwrite old pointer with newly generated value. If it is one of those rare occasions when you are not using the primary 08-09 ROM mirror then instead of 08000000 then you pick the location it uses, though frankly in most cases 08000000 will still work as it is still the ROM, just accesses at a higher priority).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 29, 2020, 02:07:06 pm
Maybe saying it's "hard" is a bit of an exaggeration on my part. I should probably be using "daunting", which would be more appropriate. I keep assuming performing these tasks would be much more complicated than they actually are. Like always, can't really confirm if it actually is until I try. Which also reminds me that I need to try the rest of the code stuff. You guys have no idea how much you're helping me, I appreciate the patience! :angel:

I'll give expanding the ROM to 16 MB a shot. Inserting the blank space at the end of the ROM isn't hard at all, what I still have doubts about is with shifting data around and what parts of the ROM constitutes what, but that'll be up to me to figure out and get the hang of.

October 29, 2020, 02:29:31 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
...I didn't even have to search that hard to find that there are a couple chunks of free space on the ROM (just a bunch of chunks filled with nothing but 00's). In fact, I can find a lot of them starting with 0067C60 thanks to HxD, with a couple of stray chunklets of filled bytes. I could still make the ROM 16 MB but I doubt it'd be of much use for the things I'm trying to do.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] on October 29, 2020, 03:50:05 pm
Be warned, 00s are not always unused.  For example, games will sometimes use fixed-length strings padded out with 0s.  You might end up adding weird text at the end of item descriptions or something if it's actually that.

There may indeed be unused space, though.  Just warning that a bunch of 00s could be either.

-[Unknown]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 29, 2020, 03:51:38 pm
So wait, if the whole ROM is available at all times, then how can I feasibly branch into the expanded part if there's a limit to how far a branch can go?

I tried going the other route, of adding free space, but I have no idea what to do next. The game doesn't boot up. I think headers in this game may be marked with "estpolis_gaiden" text, because otherwise I have no idea where they could be? This same string is repeated a couple of times in the ROM. Searching for a sea of 08's doesn't yield any satisfactory results. Do I need to add free space before headers? I legit have no idea.

October 29, 2020, 04:06:34 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Nevermind, it appears it only appears in areas of the ROM related to the debug mode.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 on October 29, 2020, 05:04:51 pm
If for some reason you are limited jump and jump again if you really want, though straight ARM jumps/branches have a 32 meg window.
http://problemkaputt.de/gbatek.htm#armopcodesbranchandbranchwithlinkbblbxblxswibkpt
Though get a bit creative and you could probably pull it off in THUMB as well http://problemkaputt.de/gbatek.htm#thumbopcodesjumpsandcalls .

You added blank data to the end of the ROM and it did not boot? I have had issues from trimmed ROMs before but adding stuff and it not working is very new here. Not sure what you did other than make it some kind of silly large size that confused the emulator (which if you were anywhere near 16 megs should not be the case).

As far as headers I presume you mean you are looking for some kind of indicator the data to follow is a text string or whatever. They don't have to such things, indeed it is rare for it to do so. Indeed I normally look for end of line markers (or something that is functionally akin to it) and compare those to what I am thinking are the pointers (end of line is usually pointer - say 4 bytes).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: LucasRCD on October 29, 2020, 05:22:57 pm
I know where I went wrong. It worked fine when I just added the doubled space at the end of the ROM. This is gonna sound ridiculous, but with the way you described things, I thought that if I were to do this (https://cdn.discordapp.com/attachments/769286995779780689/771482092869255178/unknown.png), which is to just add empty space at earlier points in the ROM and then just redirecting things later, then things would magically sort themselves out. Maybe it is possible but not with the way I went about it.

If you ignore my gigantic gaffe, then the ROM expansion was a success. It's a good thing I've got backups. Now it's time for me to experiment with writing a patch. Gonna have to read back up a few posts in order to see what I need to do.

October 29, 2020, 07:26:13 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Code: [Select]
EWRAM 0203D20C = Eldin's current JP (4 bytes)
----> 08001AC6 = Jumps here upon killing the last enemy (adds r0,r0,r4)
  \-> 03007C00 = Allocated
----> 08001AD4 = Then jumps here from 08001AC6 (ldr r3,=Lxx_5F5E0FFh)
----> 08001B2A = Then jumps here from 08001AD4 (mov r8,r2)

Did some breakpoint stuff, this was the result. I should probably do this whole documenting thing on the wiki instead of my own threads. I haven't begun work on the patch to try and get the JP meter/JP gains visible yet, I just wanted to collect the data I was overdue first.

October 29, 2020, 08:35:29 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
Alright, so I got some things out of the way. I can finally start making some progress with this. I looked on the previous page for a particular string of code, and decided to alter the header for it. So here's what I've got by replacing the one presented originally with the one I unearthed earlier:

Code: [Select]
ldr r1,=5F5E0FFh ;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

Do I have to do anything else? Or is this good enough to patch in?
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: Kajitani-Eizan on October 29, 2020, 10:19:19 pm
That's probably not what you'll want to do at first, especially since you don't have a handy pool available for the addresses.

Try first a very basic thing, like changing what value is added there, e.g.:

Code: [Select]
.open "lufia.gba",08000000h   ; Open ROM, map to 0x08000000 as per typical memory mapping for GBA
.gba                          ; Put armips in GBA mode/THUMB mode

.org 08001AC6h                ; Move insert point to this address
; add r0,r4                   ; Add r4 to r0 (original instruction)
  mov r0,20h                  ; Set value to always be 0x20, instead of adding r0 and r4 together

.close

Put in the appropriate filename for your ROM instead of "lufia.gba" and save as a .asm. Run armips with this .asm file (it will modify your ROM). If that changes the thing, you know it worked, good first step! To change it back, comment out the mov and uncomment the add (move the semicolon from one line to the other).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] on October 30, 2020, 01:18:18 am
If you want to jump somewhere far away, first you'd identify somewhere you want to replace.  Let's say there's this function:

Code: [Select]
08069D14 B500     push    r14                                     ;10
08069D16 4B0D     ldr     r3,=3001974h                            ;9
08069D18 7818     ldrb    r0,[r3]                                 ;4
08069D1A 28FF     cmp     r0,0FFh                                 ;2
08069D1C D013     beq     8069D46h                                ;8
08069D1E 480C     ldr     r0,=3001973h                            ;9
08069D20 7800     ldrb    r0,[r0]                                 ;8
08069D22 2801     cmp     r0,1h                                   ;2
08069D24 D10F     bne     8069D46h                                ;8
08069D26 4A0B     ldr     r2,=30018BCh                            ;9
08069D28 490B     ldr     r1,=3001948h                            ;9
08069D2A 7818     ldrb    r0,[r3]                                 ;4
08069D2C 3801     sub     r0,1h                                   ;2
08069D2E 0100     lsl     r0,r0,4h                                ;2
08069D30 6809     ldr     r1,[r1]                                 ;4
08069D32 1809     add     r1,r1,r0                                ;2
08069D34 60D1     str     r1,[r2,0Ch]                             ;5
08069D36 4809     ldr     r0,=3001AD8h                            ;9
08069D38 6001     str     r1,[r0]                                 ;14
08069D3A 7B88     ldrb    r0,[r1,0Eh]                             ;4
08069D3C 7110     strb    r0,[r2,4h]                              ;5
08069D3E 7BC8     ldrb    r0,[r1,0Fh]                             ;4
08069D40 7150     strb    r0,[r2,5h]                              ;5
08069D42 F001F973 bl      806B02Ch                                ;10
08069D46 BC01     pop     r0                                      ;9
08069D48 4700     bx      r0                                      ;8
08069D4A 0000
08069D4C 1974
08069D4E 0300
08069D50 1973
08069D52 0300
08069D54 18BC
08069D56 0300
08069D58 1948
08069D5A 0300
08069D5C 1AD8
08069D5E 0300

Let's suppose that you want to add more code here (such as a bunch of code to write JP to some tiles for BG 0.)  You can't just insert some new code, that would break everything.  Branches would go the wrong places, there'd be mayhem.

But what you can do is replace some code with a large jump.  Most GBA code is Thumb, because ARM code essentially runs at 50% speed on the GBA.  It can be run at full speed by copying it into WRAM and running from there, but you only have so much WRAM, so games typically only do this with performance critical code.

Okay, so let's "insert" some new code near the top of the above function.  We'll target this part:

Code: [Select]
08069D14 B500     push    r14                                     ;10
<-- add new code here
08069D16 4B0D     ldr     r3,=3001974h                            ;9

Since we can't insert, we find some free space at the end for our code... but we can't even insert a branch to go there either - are we stuck?  Nope, we just need to *replace* some code and bring it with us.

First, let's come up with the minimum code we need to get somewhere far away:

Code: [Select]
08069D16  ldr r3,=0x087E8228  ; ldr = 2 bytes
08069D18  mov r15,r3          ; mov = 2 bytes
08069D1A  dh 0x8228           ; first part of constant loaded by ldr above = 2 bytes
08069D1C  dh 0x087E           ; final part of constant loaded by ldr above = 2 bytes

We need 8 total bytes, and our new code would end at 0x08069D1E.  Note that we have to include the constant for where we're jumping.  Everything takes space.

There was code there until 0x08069D1E before:

Code: [Select]
08069D14 B500     push    r14                                     ;10
=== We're replacing this part:
=== 08069D16 4B0D     ldr     r3,=3001974h                            ;9
=== 08069D18 7818     ldrb    r0,[r3]                                 ;4
=== 08069D1A 28FF     cmp     r0,0FFh                                 ;2
=== 08069D1C D013     beq     8069D46h                                ;8
===
08069D1E 480C     ldr     r0,=3001973h                            ;9

Bad Things will happen if we just delete that old code, so we'll bring it with us to our new home.  Here's the code we'll jump to... so far doing nothing useful beyond the original game's code:

Code: [Select]
ldr r3,=0x03001974
ldrb r0,[r3]
cmp r0,0xFF

bne @@dontbeq
ldr r0,0x08069D46
mov r15,r0

@@dontbeq:
ldr r0,0x08069D1E
mov r15,r0

.pool

Wait, you say.  This is way more complex than those 4 lines.  But, see, I picked 4 harder to replace instructions on purpose to show you: there was a beq there.  beq is an instruction that can't jump all that far, so I had to replace it with a jump that can go the distance.

I swapped the logic around, doing a shorter bne to skip the longer code I need to beq.  beq is the opposite of bne, so that's safe to do.

So far, that new code does nothing.  I've just managed to make space where I can finally insert things.  Now let's insert something:

Code: [Select]
ldr r3,=0x03001974
ldrb r0,[r3]

; INSERTED CODE:
push r1
mov r1,0x02012345
strb r0,[r1]
pop r1
; END OF INSERTED CODE

cmp r0,0xFF

bne @@dontbeq
ldr r0,0x08069D46
mov r15,r0

@@dontbeq:
ldr r0,0x08069D1E
mov r15,r0

.pool

Finally, I've done something useful.  Well, maybe useful, it's just an example.  A more likely story might be logging:

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

But I could write out the JP value here.  That's what I'd do (https://github.com/unknownbrackets/tomatotrans/blob/master/asm/dialog_item.asm), but it might not be for the faint of heart.

A more common tactic is to compile some code using C or similar, and then "bl" there.  It's the same idea really, you'd just insert a "bl myfunc" (to your C function) in that same place.

-[Unknown]
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: FAST6191 on October 30, 2020, 06:06:16 am
Most GBA code is Thumb, because ARM code essentially runs at 50% speed on the GBA.  It can be run at full speed by copying it into WRAM and running from there, but you only have so much WRAM, so games typically only do this with performance critical code.

I am not convinced of that one.

There is certainly cause to learn both and expect to see both in any given game but most times I have gone to either hardcode a cheat, trace down, tweak a game just slightly so, fiddle with vblanks, or maybe have some fun function I encounter it as ARM mode. Thumb is great for injecting things into a game though where you have limited space/execution time.

I am not sure what the GBA duplicates list is at these days but that might actually make an interesting study if we are going to head towards whole ROM set analysis (I still want to see the results of a DS analysis for what uses SDAT sound). If we can figure out a way to differentiate between housekeeping and big boy code that might also be nice but that might be easier said than done (idle loops and housekeeping might well be predominantly thumb).
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: Kajitani-Eizan on October 30, 2020, 01:21:20 pm
Re: adding branches within the game code:

Rather than bothering with all that, I would recommend just identifying some other resource within bl range (e.g. some graphics) and move it to the end of the ROM, changing all references to that resource as well. Then use that space for program code that is in range. Voila, you can just bl straight to the new functions, only 4 bytes needed within the function to be hacked.

If you can only move a very small amount of stuff, or you don't want to move any stuff but you can identify a small amount of space you can use (so, not big enough to store your big new functions)... you can use the space to write veneers that will let you perform the large jump while keeping your actual code relatively clean. For example:

Function to hack in original game code:
Code: [Select]
  (stuff before)
  bl MyFunction  ; overwrites either a different bl or 2 instructions
  (stuff after)

Small island of space:
Code: [Select]
MyFunction:
  ldr r3,=MyFunctionForReal
  bx r3
.pool
(this is more or less what you wrote, but now not in the middle of other code)

End of the ROM:
Code: [Select]
MyFunctionForReal:
  push lr
  (replicate the code you overwrote in the hacked function)
  (do your stuff)
  pop lr
  bx lr

This should work fine as long as you can freely use one of r0-r3 for the veneer. If not, e.g., the function to be hacked was using all those registers, or you are writing a new function that takes more than 3 parameters, the veneer will have to be a bit longer... r12 is explicitly to be used for this purpose and you are not generally expected to preserve its value, but you can't load directly into r12 in THUMB. So maybe something like:

Small island of space:
Code: [Select]
MyFunction:
  push r4
  ldr r4,=MyFunctionForReal
  mov r12,r4
  pop r4
  bx r12
.pool

Just double check that the function you're hacking didn't make temporary use of r12, and you should be good. If it did use r12 and you also can't use any of r0-r3, then the solution will be ugly no matter what.
Title: Re: Trying to get into GBA ROM hacking, any directions for a newcomer?
Post by: [Unknown] on October 30, 2020, 01:25:38 pm
There is certainly cause to learn both and expect to see both in any given game but most times I have gone to either hardcode a cheat, trace down, tweak a game just slightly so, fiddle with vblanks, or maybe have some fun function I encounter it as ARM mode. Thumb is great for injecting things into a game though where you have limited space/execution time.

Sound and vblank code, as well as anything else related to interrupts is likely to be ARM code.  You will also see thunks in Thumb code for functions that run ARM-only instructions.

I am not sure what the GBA duplicates list is at these days but that might actually make an interesting study if we are going to head towards whole ROM set analysis (I still want to see the results of a DS analysis for what uses SDAT sound). If we can figure out a way to differentiate between housekeeping and big boy code that might also be nice but that might be easier said than done (idle loops and housekeeping might well be predominantly thumb).

I wrote a script that (with a little help in some cases it has trouble with, mostly around jump tables) scans for all reachable functions in a GBA ROM image.  This was mainly for investigation of two GBA games I was looking into.  In both cases, almost all the code is Thumb.  In these games (one early GBA lifecycle, another late) I've got a decent picture of every part of the ROM so am pretty sure I'm not missing any code.

Running this same script on Lufia, without enough help (so it's only seen about 75% of the game's code) I get 3643 functions, 99% of which are Thumb.  Even if we assume all of the functions it didn't detect are ARM, it'd still be 75% Thumb.

I've heard there are a few games that make use of ARM and swapping code into RAM, but I doubt Lufia is one of these.  Honestly, the PSP is similar: you can make good optimization of codesize by swapping in/out prx files, but only a small fraction of PSP games do this.

-[Unknown]