Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Fire Emblem Ultimate Tutorial.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
7.86 Mб
Скачать

Part 2: Breaking Down Your First asm Hack

Before breaking them down, make sure you can insert ASM hacks with little trouble. There are some ASM hacks on the Fire Emblem Shrine Forums and Serenes Forest Forums: look for them and try them out. Some might just ask you to edit hex directly, while others might ask you to use a patcher of some sort or copy some data. Whatever it is, be familiar with it: the more you know going into these things, the easier it’ll be, because you’ll have less new things to learn, if that makes sense.

So, ASM hacks are written in a .asm file, which is really just a text file with the extension .asm. Thus you can just right-click the Hector Hard Mode Hack.asm text file and edit it in Notepad++ and you’ll be off.

Oh gosh, what does THIS mean?

Don’t worry, I’ll teach you. But again, I’m not going to go over things constantly and repeat myself a ton, meaning once I teach what the .thumb code does, you’ll be expected to know it henceforth. If you need to look back on things I taught, by all means, look back—it’s not expected that you learn this all in one reading, on your first time.

To start, every code starts on a new line. There are two main types of codes here: a code that the assembler uses in terms of like, writing the program, which are codes that start with periods, and actual assembler codes, which will be inserted into the ROM—they’re usually indented and don’t start with dots. You don’t have to indent, but it’s nice for organization purposes to indent once or twice when you write an opcode and also to keep all the parameters on the same level as well. It makes scanning through code and the such easier. Good programming habits can go a long way.

Now, let’s begin:

  • .thumb sets it so that the instruction set use is THUMB. You’ll want this at the beginning of your files pretty much all the time, unless you’re using ARM, which I am NOT teaching here, because I am only teaching you what little I know about ASM hacking.

  • .org sets the offset. It’s just like the event assembler code, ORG—in fact, Nintenlord, the maker of the Event Assembler, knows ASM, and borrowed a lot of the ideas in his event assembler from knowing assembly and programming in general, I’m pretty sure. I’d go into making comparisons and such, but it’s not really relevant. For this example, we want the program to write to the offset 0x00, so we tell it that. 0x00 is the same as 0x0000000000, FYI. Also, this code is totally important, just like the .thumb code.

  • There is a blank line at the end. Well, several, in this case, but in general, you just need one. The assembler will complain if you don’t have one. Give it one. Don’t let it complain.

Okay, we’re done for now. Yeah, I totally just avoided the actual assembly there. Teehee. That’s next:

ldr: ldr is a very important code. It loads a word to a register. Oh man, what’s a register?! Looks like I need to take a break already so I can introduce registers:

Registers are like little slots where you can store values. They’re like boxes, each one with their own value, up to a word long. You can store information in them and load information from them, but they’re just temporary—they don’t really do anything. However, they’re also variables.

What are variables? Study up on’em, bud, the general idea is important—how it applies here is that when I say “r1”, I’m really talking about whatever is in r1. We don’t know exactly what it is because it depends, so we just reference it as a variable here. Instead of saying “move the specific value ____ in box r1”, we just say “move box r1”. It’s actually a lot simpler in practice than I’m explaining here, so let’s just continue on.

ldr: ldr is a very important code. It loads a word to a register. What the word is depends on what comes after the comma. In this hack we have the code:

ldr r1, =0x0202BC13

ldr tells us it’s loading a word, or 4 bytes, into a register—the register r1 (technically the 2nd register because there is an “r0” as well). The value we are loading is designated by what is after the “=”, 0x0202BC13. In the ldr code, the equal sign is needed so that it knows it’s loading that value. I don’t know the specifics, but just use it. XP

Okay, so before I continue introducing codes, I need to tell you something else. It’s a very good idea to keep track of what register holds what. On that note, you may want to keep a separate text file with notes (including what the heck that word “0x0202BC13” is might be helpful too :P) but you may also want to add comments.

To add comments, just add the @ sign, followed by a space (I’m actually not sure if the space after the “@” sign is necessary, but I do it anyway because I was never taught formally so I just copied what I saw, haha), followed by the comment. You can do this on a new line or append it to a line of code. So we could type in

ldr r1, =0x0202BC13 @ Loads the word 0x0202BC13 to r1

and it would have the same effect as before. The @ sign and everything after it are ultimately ignored.

Furthermore, you may want to keep track in general when you edit values in registers (which is pretty much all the time) so that you know what register holds what. Often times you have some intended operation you’re trying to do and when finding bugs/glitches, it’s good to know what EXACTLY are the numbers going through the system. Sometimes though, you’ll load a variable into the system, in which case you just have to put in some example value and run through the program in your head and test things to see how it turns out in various situations (you must always test multiple situations once we get onto conditional branching, which says “if this, do this, or else, do that”, a common theme in programming languages.

Oh boy, more rants and information for you to absorb. I told you it wouldn’t be easy. I’m not even giving lots of nice pictures to work with. Text, text, text, and more text.

By the way, it might seem silly to keep track of all of this in your head—that’s why eventually, I’ll teach you about using debuggers, which will let you run through the code systematically, using a program, and really help you keep track of what’s happening. It’ll also help with a lot of other things. But step-by-step—you’ve got a while to go before we get to that point.

mov r0, #0x03

The “mov” opcode does what you might think—it “moves” values around. In this case, we are “moving” the value 0x03 into register 0, r0. As for where we’re moving it FROM… don’t think too much about that, alright? Think of it as just saying “r0 = 0x03” in this case. We can also do something like mov r0, r1, which would say r0 = r1… which is slightly confusing, because you might wonder “so does r1 become r0 or does r0 become r1?” and the answer is “r1 becomes r0” because if mov r0, #0x03 makes r0 = 0x03, then mov r0, r1 makes r0 = whatever value is in r1.

By the way, the “#” sign next to 0x03 is key. It has to know it’s a numeric value. Don’t forget the # sign.

strb r0, [r1]

We’re making progress! This code sort of does the opposite of ldr—it stores values instead of loading them. However, this code actually stores a byte, not a word. How do we know? Because the opcode is “strb”, which stands for “store byte”, where the “b” is for “byte”. If there wasn’t a “b”, it would store a word. If there was an “h”, i.e. “strh”, it’d store a half-word, or 2 bytes. Of course, the load function has similar variations, though it also has two more variations. Let’s take a look at thumbref:

LDR (okay, they capitalize it, I don’t, big deal) loads a word into a register. We know this. Thumbref tells us this too—the first column is the name or “mnemonic” of the opcode. The second is a very short description of what it does. The third is a list of possible formats you can use the code in—essentially, you have a little bit of freedom as to how you use the code, i.e. what parameters you use. The fourth column specifies what the variables are and the such—right now, they don’t make too much sense, even to me, but thumbref DOES give definitions of the symbols.

Let’s break down Rd = [Rn + Rm], which is under every row in the fourth column of that image I showed.

Rd = destination register, according to this. In other words, it’s the register that is being effected.

Rn = a register. “n” here is generic. We can put whatever we want. It’s just saying that it’s some register we choose.

Rm = another register, this time just called “Rm”.

+ means plus/add, meaning we’re adding the register Rn and Rm together. I’m sure you guys can handle some addition.

[ ] are brackets that… it’s hard to explain, but it’s like instead of loading the value Rn + Rm, it loads the value at the ADDRESS Rn + Rm. Essentially, it treats whatever is in the bracket as an offset, instead of just some arbitrary value.

Anyhow, they’re important, and they’re there because the opcode format expects it. Similarly, be sure that you don’t forget it—thumbref is useful like this because you can always check the code format to make sure you’re using it right, or using the variant that you want to use. (The assembler will likely give an error if you use a code in a completely wrong format, since it won’t know what to do with it.)

Some of the other symbols we’ll get to later, and some of the others I still don’t really understand myself, so yeah…

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]