User Tools

Site Tools


zero_mission:intermediate_guides:yohannasm

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
zero_mission:intermediate_guides:yohannasm [2024/03/23 19:25] felixwrightzero_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), the BG0Position (0x30000e4), the address to our freespace (0x8760d50), the Sprite AI Pointers (0x875E8C0) and our constant which is going to be the Sprite ID of the sprite we will hijack, in our case it’s 0x6c :+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''), the BG0Position (''0x30000e4''), the address to our freespace (''0x8760d50''), the Sprite AI Pointers (''0x875E8C0'') and our constant which is going to be the Sprite ID of the sprite we will hijack, in our case it’s ''0x6c'' :
  
 <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 ''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.
  
 ==== Hijack ==== ==== Hijack ====
Line 221: Line 221:
 </code> </code>
  
-.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…+''.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 ''.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.
  
 ==== 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 ''ldr'' (LoaD Register), the syntax is like this :
  
 <code arm> <code arm>
Line 244: Line 244:
 </code> </code>
  
-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 ''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 :
  
 <code arm> <code arm>
Line 250: Line 250:
 </code> </code>
  
-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 ''r1'', the halfword contained in ''r0'' at offset ''0''. In C this would translate to :
  
-<code arm>+<code c>
 r0 = 0x300006e; r0 = 0x300006e;
 ushort r1 = *(ushort*)r0[0]; ushort r1 = *(ushort*)r0[0];
 </code> </code>
  
-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 ''r0'' points to in ''r1'', so now ''r1'' contains the actual IRAM value of the Effect Y Position Offset.
  
 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 ''strh'' (Store Register Halfword) :
  
 <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 ''.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''.
  
 ==== 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. +''armips.exe Test.asm'' 
-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 ''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 :
  
 <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->Spriteset Editor), remove all the sprites using the “Remove slot” button, add a sprite using the “Add slot” button and choose the sprite number 6c in the combo box, it should have graphics that spell “Gekitai machine”. Click on apply to save your changes and close the Spriteset Editor. Enter Object editing mode by clicking on the red ball in the tool bar on the left, and remove all the sprites of the room by right clicking on the green squares and selecting “Remove sprite”, now add a new sprite (position doesn’t matter). Right click and select “Test Room Here”, if everything worked correctly, you should see the lava going up automatically.+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->Spriteset Editor), remove all the sprites using the “Remove slot” button, add a sprite using the “Add slot” button and choose the sprite number 6c in the combo box, it should have graphics that spell “Gekitai machine”. Click on apply to save your changes and close the Spriteset Editor. Enter Object editing mode by clicking on the red ball in the tool bar on the left, and remove all the sprites of the room by right clicking on the green squares and selecting “Remove sprite”, now add a new sprite (position doesn’t matter). Right click and select “Test Room Here”, if everything worked correctly, you should see the lava going up automatically.
  
 Congratulations, you just created your first ASM patch ! Congratulations, you just created your first ASM patch !
zero_mission/intermediate_guides/yohannasm.1711221925.txt.gz · Last modified: 2024/03/23 19:25 by felixwright