• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best places on the 'net to talk Pokémon and more! Community members will not see the bottom screen advertisements.
  • Want to share your adventures playing Pokémon?
    Check out our new Travel Journals forum for sharing playthroughs of ROM Hacks, Fan Games, and other Pokémon content!
  • IMPORTANT: Following a takedown request, the following hacks have been delisted from PokéCommunity:

    • Pokémon Glazed
    • Pokémon: Giratina Strikes Back
    • Pokémon Flora Sky
    • Pokémon Stranded
    The downloads and discussion threads for these hacks will no longer be accessible, and staff will be unable to return questions regarding accessing this content.

GBA ASM Programming

colcolstyles

Yours truly
1,588
Posts
15
Years
quick question, how would i make a pokemon base stat go higherthan 255? i know this requirs asm and if i over looked it and its in this tut plz tell me so your time isn't wasted any more

You will have to expand the pokémon data structure so that the six base stats will all be halfowrds (16-bit) instead of bytes (8-bit). You will also have to change the references to the data table because each entry (i.e., each pokémon's data) will now be longer. Then you'll have to hunt down every single routine that loads a pokémon's base stats and change them so that each one loads halfwords instead of bytes. You possibly will also have to make some changes to these routines as they will be interpreting the data as bytes.

In other words, just give up.
 
94
Posts
13
Years
  • Seen Nov 2, 2016
Quick question. When you load the status byte and want to separate the 3 sleep bits, why not just and it by 7? I'm just starting out with assembly but I was wondering why you shifted the bits to clear instead of just using and.
 

Xenesis

Syogun Changer
55
Posts
17
Years
Using shifts to clear bits has it's advantages. Mainly because to and something you need to load a value into a register and then and between two registers. Using bitshifts to cut off bits you don't care about is often simpler because it requires only one register.

Basically, as a consequence of the processor design there's no function for AND rX, Value, just AND rX, rY

Here's a summary of all the ALU operations from gbatek:

Code:
THUMB.4: ALU operations

Opcode Format

  Bit    Expl.
  15-10  Must be 010000b for this type of instructions
  9-6    Opcode (0-Fh)
           0: AND Rd,Rs     ;AND logical       Rd = Rd AND Rs
           1: EOR Rd,Rs     ;XOR logical       Rd = Rd XOR Rs
           2: LSL Rd,Rs     ;log. shift left   Rd = Rd << (Rs AND 0FFh)
           3: LSR Rd,Rs     ;log. shift right  Rd = Rd >> (Rs AND 0FFh)
           4: ASR Rd,Rs     ;arit shift right  Rd = Rd SAR (Rs AND 0FFh)
           5: ADC Rd,Rs     ;add with carry    Rd = Rd + Rs + Cy
           6: SBC Rd,Rs     ;sub with carry    Rd = Rd - Rs - NOT Cy
           7: ROR Rd,Rs     ;rotate right      Rd = Rd ROR (Rs AND 0FFh)
           8: TST Rd,Rs     ;test            Void = Rd AND Rs
           9: NEG Rd,Rs     ;negate            Rd = 0 - Rs
           A: CMP Rd,Rs     ;compare         Void = Rd - Rs
           B: CMN Rd,Rs     ;neg.compare     Void = Rd + Rs
           C: ORR Rd,Rs     ;OR logical        Rd = Rd OR Rs
           D: MUL Rd,Rs     ;multiply          Rd = Rd * Rs
           E: BIC Rd,Rs     ;bit clear         Rd = Rd AND NOT Rs
           F: MVN Rd,Rs     ;not               Rd = NOT Rs
  5-3    Rs - Source Register       (R0..R7)
  2-0    Rd - Destination Register  (R0..R7)

As you can see, they only work between two registers (with the exception of the NOT/NEG operations).
 
Last edited:
94
Posts
13
Years
  • Seen Nov 2, 2016
Using shifts to clear bits has it's advantages. Mainly because to and something you need to load a value into a register and then and between two registers. Using bitshifts to cut off bits you don't care about is often simpler because it requires only one register.
If I'm not mistaken though and directly edits the contents of one register, so it only requires one register as well.
 

colcolstyles

Yours truly
1,588
Posts
15
Years
I'm pretty sure it takes two. Let's say you have some value in r0. In order to clear the top 29 bits, you would have to load 7 into an arbitrary register and then AND the two. I can't think of any way to do it with only one register other than to use logical shifts. Plus, I think that the "mov" instruction takes up more cycles than logical shifts so it'll save you a nanosecond or two. :D
 

Xenesis

Syogun Changer
55
Posts
17
Years
If I'm not mistaken though and directly edits the contents of one register, so it only requires one register as well.

Yes, that's correct.

However, you can't AND an immediate value in code, you have to AND two registers.

Eg, you can't go:

AND r0, #0x3

because the hardware doesn't support it.

You have to go something like:

MOV r1, #0x3
AND r0, r1

Which requires two free registers. If you want to clear bits, you can just do something like:

lsl r0, r0, #0x19
lsr r0, r0, #0x19

Which only requires one free register.

Plus, I think that the "mov" instruction takes up more cycles than logical shifts so it'll save you a nanosecond or two. :D

The difference between the two is generally rather minor. You're unlikely to add much bloat to the game's code as is unless you start abusing swi operations relentlessly.
 

colcolstyles

Yours truly
1,588
Posts
15
Years
The difference between the two is generally rather minor. You're unlikely to add much bloat to the game's code as is unless you start abusing swi operations relentlessly.

True, although if the code is in a loop and you're already pressed for time (which you shouldn't be if you're hacking a commercial ROM), it could possibly make a difference. Actually, if this is to be used in a loop, you're probably better off "mov"-ing the 7 into a register outside the loop so that you only need one instruction (an "and") to clear bits while inside the loop.
 
94
Posts
13
Years
  • Seen Nov 2, 2016
Thanks Xenesis, colcolstyles. There was just one more thing that wasn't clear to me:
.word 0x020270B6 + (0x800D * 2)
If the 0x8000-0x8013 variables are the only static one, how would there be an address of the "first" variable(I assume 0x0000), wouldn't it be DMA along with the rest?

BTW, looking at an example code from a tutorial JPAN posted a while ago, he subtracts 0x8000 from his variable values, multiplies them by 4, then finally adds that to the 0x8000 variable's address. I don't understand why it would be necessary to do that(or how that works quite frankly), even though with the code in this tutorial you can simply store the value to loaded variable.
Here was the code:
Code:
                          .align 2
                          .thumb
  Var_adder:      push {r0-r2, lr}
                          Ldr r0, first_var_addr @this will load the address of that lable
                          Ldrh r0, [r0, #0x0]      @and this will load its content.
                          Ldr r1, second_var_addr
                          Ldrh r1, [r1, #0x0]      @both variable numbers are loaded   
                          Lsl r2, r2, #0x10          @cleans the bottom half of register r2
                          Add r2, r2,#0x8          @places 0x8 in r2
                          Lsl r2, r2, #0xc            @and this turns 0x8 in 0x8000, and cleans the rest                                                               @of r2             
                          Sub r1, r1, r2               @leaves only the last value in
                          Sub r0, r0, r2               @each variable.
                          Lsl r1, r1, #0x2            @after multiplied by 4, It becomes the 
                                                              @offset of that address
                          Ldr r2, var_8000_addr
                          Lsl r0, r0, #0x2            @same here.
                          Add r0, r2, r0              @by adding the variable address to the offest
                          Add r1, r2, r1              @you get the correct variable address
                          Ldrh r2, [r0, #0x0]      @now we load the content of the variables we
                          Ldrh r1, [r1, #0x0]      @want to add
                          Add r2, r1, r2              @and add them
                          Strh r2, [r0, #0x0]       @the result, that is in r2, is placed in the first                                                                        @variable, the one in 0x8013
                          Pop {r0-r2, pc}           @and we're done
   
  first_var_addr: .word 0x020370dc
  second_var_addr:.word 0x020370de
  var_8000_addr:.word 0x020370b8
 

阴魂君

_(:зゝ∠)_ so busy i am…
22
Posts
11
Years
Excuse me,I don't know why,but I can't download the asm pack in China... Could you please send it to my email? My email address is [email protected]
thanks a lot >_<
 
33
Posts
10
Years
  • Age 28
  • Seen Sep 23, 2022
Just curious here, I would need to use ASM to block players from challenging certain trainers (Gym Leaders, Rivals) with pokémons above a certain level, right?
What if I need to block items during a certain battle?

I'm just starting out, so I wanted to make my first hack more simple to understand mapping and scripting better, but if I need ASM to get some level and item caps then I'll have to learn it as well.

Thanks for the tutorial, looks very interesting, I'll definitely read it later.
 

Blah

Free supporter
1,924
Posts
11
Years
Just curious here, I would need to use ASM to block players from challenging certain trainers (Gym Leaders, Rivals) with pokémons above a certain level, right?
What if I need to block items during a certain battle?

I'm just starting out, so I wanted to make my first hack more simple to understand mapping and scripting better, but if I need ASM to get some level and item caps then I'll have to learn it as well.

Thanks for the tutorial, looks very interesting, I'll definitely read it later.

For blocking players from challenging certain trainers depending on party pokemon level you need some asm, but it's just function calls, nothing down and dirty.

For the item one, you'd need a battle script (look up Jambo's battle script tutorial/tool). Though admittedly, battle scripts are also very technical P:
 
33
Posts
10
Years
  • Age 28
  • Seen Sep 23, 2022
For blocking players from challenging certain trainers depending on party pokemon level you need some asm, but it's just function calls, nothing down and dirty.

For the item one, you'd need a battle script (look up Jambo's battle script tutorial/tool). Though admittedly, battle scripts are also very technical P:

Really? That's great news!

Mind to elaborate what asm routines I would need to do the level caps?
I really don't want to go in blind and break the game.
And are you saying that locking the items mid-battle require just some scripting? Can it be done in XSE or would I need Jambo's tool?

Thanks for the answers. Really helped.
 

Blah

Free supporter
1,924
Posts
11
Years
Really? That's great news!

Mind to elaborate what asm routines I would need to do the level caps?
I really don't want to go in blind and break the game.
And are you saying that locking the items mid-battle require just some scripting? Can it be done in XSE or would I need Jambo's tool?

Thanks for the answers. Really helped.

Sure, for the prevention of player challenging trainers, it's 90% handled by the trainer script.

I would do this:
Code:
#dyn 0x740000
#org @start
lock
faceplayer
setvar 0x4011 0x[max level of trainer]
callasm 0x[asm that returns max pokemon level in party]
compare 0x4001 LASTRESULT
if > jump @ignore
trainerbattle 0x0 0xID 0x0 @intro @defeat
msgbox @afterwards
callstd MSG_NORMAL
release
end

#org @ignore
msgbox @noThanks
callstd MSG_NORMAL
release
end

#org @noThanks
= Sorry, you wouldn't be a\nchallenge to me!

#org @intro
= Battle started, say something

#org @defeat
= defeat text

#org @afterwards
= Nice battle.

For the item blocking, I have no idea. I think Jambo's tutorial on Battle scripts covers it iirc.
 

ZapdosMan

The Principality
38
Posts
9
Years
  • Age 28
  • Seen May 15, 2016
Wow I think this is a really good tutorial
though i find it hard to understand but finally someone posted a tutorial on this

Thanks

ZapdosMan
 

Sounak

Black Charizard
7
Posts
9
Years
  • Age 34
  • Seen May 1, 2018
The download link to your ASM pack is not working.
Can you re-upload it please.
 
794
Posts
10
Years
I have a problem with your first routine. Here's what I got http://i.imgur.com/obuckLm.png
My code:
Spoiler:

I also tried those ( 03 B5 02 48 80 88 02 49 08 80 03 BD 84 42 02 02 D0 70 03 02 ) assembled numbers and still got the same result. Why is this happening?
 

GoGoJJTech

(☞゚ヮ゚)☞ http://GoGoJJTech.com ☜(゚ヮ゚☜)
2,475
Posts
11
Years
I have a problem with your first routine. Here's what I got http://i.imgur.com/obuckLm.png
My code:
Spoiler:

I also tried those ( 03 B5 02 48 80 88 02 49 08 80 03 BD 84 42 02 02 D0 70 03 02 ) assembled numbers and still got the same result. Why is this happening?

That routine seems to be a failure. You're trying to load the level but you're loading a halfword (two bytes).
Change "ldrh r0, [r0]" to "ldrb r0, [r0]"
 
Back
Top