This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
zero_mission:intermediate_guides:yohannasm [2024/03/23 19:25] – felixwright | zero_mission:intermediate_guides:yohannasm [2024/03/23 19:39] (current) – felixwright | ||
---|---|---|---|
Line 195: | Line 195: | ||
- | To make things easier, we will define labels that will hold constants, this is especially useful for IRAM and ROM addresses, here we’ll need 2 IRAM addresses, 2 ROM addresses and one constant, the Effect Y Position Offset (0x300006e), | + | To make things easier, we will define labels that will hold constants, this is especially useful for IRAM and ROM addresses, here we’ll need 2 IRAM addresses, 2 ROM addresses and one constant, the Effect Y Position Offset ('' |
<code arm> | <code arm> | ||
Line 209: | Line 209: | ||
Sprite AI Pointers is an array of pointers to all the main AI of the sprites, this is where we’ll put a pointer to our freespace. | Sprite AI Pointers is an array of pointers to all the main AI of the sprites, this is where we’ll put a pointer to our freespace. | ||
- | Freespace is unused data in the ROM where we can safely put our code, open the ROM in HxD and go to to our freespace address (without the 8 at the beginning because HxD doesn’t work with banks), you will see a lot of FF, this is what freespace usually looks like, repeated data. | + | Freespace is unused data in the ROM where we can safely put our code, open the ROM in HxD and go to to our freespace address (without the '' |
==== Hijack ==== | ==== Hijack ==== | ||
Line 221: | Line 221: | ||
</ | </ | ||
- | .org tells ARMIPS to go insert code at the location provided after, in our case it’s going to be SpriteAIPointers + SpriteID * 4 ; we start at SpriteAIPointers and then we add our SpriteID multiplied by 4 to offset the position to the pointer to the AI of our sprite. The multiplication by 4 is needed because a pointer is 32 bits long or 4 bytes long, so the first pointer is at offset 0, then the second at offset 4, then 8… | + | '' |
- | The .dw tells ARMIPS to generate a pointer to the address provided, in our case the freespace + 1. You may be wondering why we added 1, adding one to a function start offset tells the CPU to switch to THUMB mode, since our code will be written in THUMB we need to switch modes otherwise it’ll go back to ARM mode and the game will crash. | + | The '' |
==== Actual Code ==== | ==== Actual Code ==== | ||
Line 238: | Line 238: | ||
Next, we’re going to decrement the Effect Y Position Offset (the origin is at the top-left of the screen, since we want it to go up we are decrementing it). | Next, we’re going to decrement the Effect Y Position Offset (the origin is at the top-left of the screen, since we want it to go up we are decrementing it). | ||
- | To start, we load the IRAM address to r0 by using ldr (LoaD Register), the syntax is like this : | + | To start, we load the IRAM address to r0 by using '' |
<code arm> | <code arm> | ||
Line 244: | Line 244: | ||
</ | </ | ||
- | Now r0 contains the value we put in our label, so 0x300006e, we then need to actually load the value that the address points to, for that we use ldrh (LoaD Register with Halfword). Halfword means the data we are loading is 16 bit sized or 2 bytes, if we wanted to load an 8 bit/1 byte value we would use ldrb and if we wanted to load a 32 bit/4 bytes value we would just use ldr. Syntax goes like this : | + | Now '' |
<code arm> | <code arm> | ||
Line 250: | Line 250: | ||
</ | </ | ||
- | Here we are loading into r1, the halfword contained in r0 at offset 0. In C this would translate to : | + | Here we are loading into '' |
- | < | + | < |
r0 = 0x300006e; | r0 = 0x300006e; | ||
ushort r1 = *(ushort*)r0[0]; | ushort r1 = *(ushort*)r0[0]; | ||
</ | </ | ||
- | In other words, we are just loading the 2 bytes value that r0 points to in r1, so now r1 contains the actual IRAM value of the Effect Y Position Offset. | + | In other words, we are just loading the 2 bytes value that '' |
Let’s decrement our value now : | Let’s decrement our value now : | ||
Line 267: | Line 267: | ||
This is fairly simple, sub just subtracts the given register with the given value so this is the same as doing r1 -= 3. | This is fairly simple, sub just subtracts the given register with the given value so this is the same as doing r1 -= 3. | ||
- | All we need to do is store our new value to IRAM now, so instead of doing a load, we are going to do a store : | + | All we need to do is store our new value to IRAM now, so instead of doing a load, we are going to do a '' |
<code arm> | <code arm> | ||
Line 300: | Line 300: | ||
Last very important thing to do is to add .pool at the very end of our code (right after the bx r0). | Last very important thing to do is to add .pool at the very end of our code (right after the bx r0). | ||
- | We need a .pool because of the way instructions are assembled, in THUMB each instruction (except bl) is 16 bits long, but IRAM addresses are 32 bits long, so how can our ldr works ? Well instead of directly loading the address, we will create a pointer to that said address right after the code, and instead load the value of that pointer in our ldr, meaning that now the address loaded can fit in the 16 bites instruction. All this process is handled by the .pool directive, it’ll automatically create a pointer and replace our ldr. | + | |
+ | We need a '' | ||
==== Assembling & Testing ==== | ==== Assembling & Testing ==== | ||
Line 306: | Line 307: | ||
Now that our code is ready, we need to assemble it using ARMIPS, open the command line tool in the folder where everything is and simply type : | Now that our code is ready, we need to assemble it using ARMIPS, open the command line tool in the folder where everything is and simply type : | ||
- | armips.exe Test.asm | ||
- | Press enter and if everything works, no message should appear but you should have a new ROM named “TestASM.gba” in your folder. | + | '' |
- | If it didn’t work, try and debug it yourself, you very likely did an error in the code or didn’t renamed your vanilla ROM to “ZM_U.gba”. In case you need it, here’s the entire source code : | + | |
+ | Press enter and if everything works, no message should appear but you should have a new ROM named '' | ||
+ | If it didn’t work, try and debug it yourself, you very likely did an error in the code or didn’t renamed your vanilla ROM to '' | ||
<code arm test.asm> | <code arm test.asm> | ||
Line 345: | Line 347: | ||
If it still doesn’t work, come ask for help in the MAGConst discord server, here’s an invite link if needed. | If it still doesn’t work, come ask for help in the MAGConst discord server, here’s an invite link if needed. | ||
- | Now let’s test our code, open the new ROM (TestASM.gba) in MAGE and navigate to the fifth room in Kraid. Open the Spriteset Editor (Editor-> | + | Now let’s test our code, open the new ROM ('' |
Congratulations, | Congratulations, |