• 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?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Help Thread: ASM & Disassembly

Status
Not open for further replies.
  • 46
    Posts
    9
    Years
    • Seen Dec 16, 2015
    Try setting 0x8002 to 0xFF. See if it turns shiny. Lets continue this discussion in the ASM help thread or something. We're kind of de-railing on this thread's purpose. At any rate, this is a problem with something in your ROM/execution rather than the routines. I have this routine setup in my ROM, and I've used similar for chain fishing which as worked fine.

    I'm not denying that my execution is screwing up, it's just that I've looked it over a million times and can't find where.

    Anyways, I wrote in a NPC that set 0x8002 to 0xFF, still no shinies. So that confirms something is wrong in the first two codes and not shiny charm I suppose. Since the RNG is literally just compiling a code, I don't see what could go wrong there. So it must be the shiny encounter code. Did you take a look at the code I posted in the other thread?
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    I'm not denying that my execution is screwing up, it's just that I've looked it over a million times and can't find where.

    Anyways, I wrote in a NPC that set 0x8002 to 0xFF, still no shinies. So that confirms something is wrong in the first two codes and not shiny charm I suppose. Since the RNG is literally just compiling a code, I don't see what could go wrong there. So it must be the shiny encounter code. Did you take a look at the code I posted in the other thread?

    Yes, I've seen it and it looks right to me :x

    Hmm, it's possible that the variable byte reading/storing might be causing the bugs you're experiencing. Try these steps.

    In Shiny Generator change
    Code:
    ldr r0, =(0x20370BC) @0x8002 is shiny flag
    ldrb r0, [r0]
    cmp r0, #0xFF
    into
    Code:
    ldr r0, =(0x20370BC) @0x8002 is shiny flag
    ldrh r0, [r0]
    cmp r0, #0xFF

    and
    Code:
    ldr r0, =(0x20370BC) @set back to 0x0 because ...
    mov r1, #0x0
    strb r1, [r0]
    into
    Code:
    ldr r0, =(0x20370BC) @set back to 0x0 because ....
    mov r1, #0x0
    strh r1, [r0]
     
  • 46
    Posts
    9
    Years
    • Seen Dec 16, 2015
    Yes, I've seen it and it looks right to me :x

    Hmm, it's possible that the variable byte reading/storing might be causing the bugs you're experiencing. Try these steps.

    In Shiny Generator change
    Code:
    ldr r0, =(0x20370BC) @0x8002 is shiny flag
    ldrb r0, [r0]
    cmp r0, #0xFF
    into
    Code:
    ldr r0, =(0x20370BC) @0x8002 is shiny flag
    ldrh r0, [r0]
    cmp r0, #0xFF

    and
    Code:
    ldr r0, =(0x20370BC) @set back to 0x0 because ...
    mov r1, #0x0
    strb r1, [r0]
    into
    Code:
    ldr r0, =(0x20370BC) @set back to 0x0 because ....
    mov r1, #0x0
    strh r1, [r0]

    Still no dice...

    This is frustrating. All of the right offsets and pointers are in the right places correct? Because if it's not that at this point then I'm beyond puzzled.
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Still no dice...

    This is frustrating. All of the right offsets and pointers are in the right places correct? Because if it's not that at this point then I'm beyond puzzled.

    Yeah, without debugging myself, I can't draw any other reasons why yours isn't working. Just to check, you are using English U.S FireRed BPRE ROM right?
     
  • 46
    Posts
    9
    Years
    • Seen Dec 16, 2015
    Yeah, without debugging myself, I can't draw any other reasons why yours isn't working. Just to check, you are using English U.S FireRed BPRE ROM right?

    In a way. I actually used UltraViolet as a base, which used Firered as a base. But I changed the header back so it should be functioning just like a Firered ROM with some minor changes, which is what UV is.
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    After my problem I was trying to think of a way around it.

    I stumbled across this ASM routine for naming the rival - and thought it might be useful to make a similar routine to name the player, whilst avoiding the pop-up start menu.

    Would it be hard to alter this to change the [player] name rather than [rival]?

    I haven't tried the existing routine, or even tested this one actually. It looks like the rival naming and player naming routines both use the same routine as the Pokemon naming routine. It's actually quite useful because this naming routine can be adjusted to name pretty much EVERYTHING.

    Just taking a quick look at this routine, to name the player you'd change it a light bit like this:
    Code:
    .text
    .align 2
    .thumb
    .thumb_func
    
    main:
    	push {r0-r4, lr}
    	ldr r0, =(0x80568E0 +1) @callback routine; script continuer
    	str r0, [SP, #0x4]
    	ldr r1, =(0x300500C)
    	ldr r1, [r1]
    	mov r0, #0x0
    	mov r2, #0x0
    	mov r3, #0x0
    	@setting lastresult to 0x0, you'll see soon why
    	ldr r4, =(0x20370D0)
    	strb r0, [r4]
    	ldr r4, =(0x809D954 +1)
    	bl linker
    
    checkValidName:
    	ldr r0, =(0x300500C)
    	ldr r0, [r0]
    	ldrb r0, [r0]
    	cmp r0, #0xFF
    	beq invalid
    	cmp r0, #0x0
    	beq invalid
    
    done:
    	pop {r0-r4, pc}
    
    invalid:
    	@Here, whoever owns the original routine assigns a default name.
    	@you can either loop back, assign a default name...or even better
    	@set a variable to flag that the name was invalid, and in the script prompt again
    	ldr r0, =(0x20370D0) @lastresult will be set to 0x1
    	mov r1, #0x1
    	strb r1, [r1]
    	pop {r0-r4, pc}
    	
    linker:
    	bx r4
    	
    .align 2

    Try it and report back with your findings. You don't need to control overflow because r0 being 0x0 not only makes the OW that appear to be the hero, but also limits the name size to 7 characters!

    EDIT: If the original routine creator wanted credits, please give them to him. I just simply modified his routine after a little bit of research.

    EDIT2: Magic says it works~
     
    Last edited:
  • 88
    Posts
    13
    Years
    • Seen Jun 18, 2020
    Does someone know the offset of the routine which calculates the damages in a battle ? Thanks !
     
  • 1
    Posts
    9
    Years
    How well would knowledge of another assembly language transfer over? I am pretty good at 6502 Assembly but I am really dreading having to relearn assembly for a whole new system..
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    How well would knowledge of another assembly language transfer over? I am pretty good at 6502 Assembly but I am really dreading having to relearn assembly for a whole new system..

    About 90% of the raw ASM is the same, there are some conceptually different things going on. For example, there aren't any builtin "print" style functions (except the BIOS functions swi) and functions in general are called a little differently. Also "lda" ect is not used. I would argue the actual ASM isn't hard, the hard parts are conceptual walls which need to be conquered. You need to get used to and learn how to write code that won't break the current ROM's infrastructure, and you need to acquire some good debugging/research sense.

    So to answer your question, the transition isn't hard language wise (I started ASM with MIPS), but conceptually there's a lot changing when you're editing existing code mechanics.
     

    jiangzhengwenjzw

    now working on katam
  • 181
    Posts
    11
    Years
    • Seen today
    About 90% of the raw ASM is the same, there are some conceptually different things going on. For example, there aren't any builtin "print" style functions (except the BIOS functions swi) and functions in general are called a little differently. Also "lda" ect is not used. I would argue the actual ASM isn't hard, the hard parts are conceptual walls which need to be conquered. You need to get used to and learn how to write code that won't break the current ROM's infrastructure, and you need to acquire some good debugging/research sense.

    So to answer your question, the transition isn't hard language wise (I started ASM with MIPS), but conceptually there's a lot changing when you're editing existing code mechanics.

    Hello, FBI.
    Could you tell me something about how to use these 3 functions:
    1.swi
    2.ldmia
    3.stmia

    Thank you greatly.
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Hello, FBI.
    Could you tell me something about how to use these 3 functions:
    1.swi
    2.ldmia
    3.stmia

    Thank you greatly.

    SWI is short for software interrupt. It's basically like a table (not really, but a good way to think about what it is like) of functions which are built in. You call these functions by using SWI #0xValue to do a specific BIOS function call. Some common ones are CPU_Memset, memcpy and a few mathamatical ones (there are even some for TAN/SIN/COS functions as well as simple division!).

    ldmia and stmia are basically multiple load/store operations (like a looped ldr and str). It's a useful way to save OPcodes and trivial operations thereby boosting efficiency. The syntax is a little wierd in comparison to other OPCodes, but once you understand how it works it's simple.
    Code:
    @example of a memory copy
    ldr r0, source
    ldr r1, destination
    ldmia r0! {r2-r6} @loads 5 words from memory locations in r2-r6. Increments r0.
    stmia r1!, {r2-r6} @Similar to previous, but stores
    
    @note that high registers can't be used in these
    @also note the syntax, from GBATEK:
    @
     STMIA Rb!,{Rlist}
     LDMIA Rb!,{Rlist}
    
    @rb = Base register
    @Rlist = register list ; same syntax as push/pop instructions
    
    @GBATEK also states that these are aliases to POP and PUSH. You can read in detail there~
     

    jiangzhengwenjzw

    now working on katam
  • 181
    Posts
    11
    Years
    • Seen today
    SWI is short for software interrupt. It's basically like a table (not really, but a good way to think about what it is like) of functions which are built in. You call these functions by using SWI #0xValue to do a specific BIOS function call. Some common ones are CPU_Memset, memcpy and a few mathamatical ones (there are even some for TAN/SIN/COS functions as well as simple division!).

    ldmia and stmia are basically multiple load/store operations (like a looped ldr and str). It's a useful way to save OPcodes and trivial operations thereby boosting efficiency. The syntax is a little wierd in comparison to other OPCodes, but once you understand how it works it's simple.
    Code:
    @example of a memory copy
    ldr r0, source
    ldr r1, destination
    ldmia r0! {r2-r6} @loads 5 words from memory locations in r2-r6. Increments r0.
    stmia r1!, {r2-r6} @Similar to previous, but stores
    
    @note that high registers can't be used in these
    @also note the syntax, from GBATEK:
    @
     STMIA Rb!,{Rlist}
     LDMIA Rb!,{Rlist}
    
    @rb = Base register
    @Rlist = register list ; same syntax as push/pop instructions
    
    @GBATEK also states that these are aliases to POP and PUSH. You can read in detail there~

    Thank you for your reply. I have now developed a basic idea of swi and I've found something about it in gbatek. But there's many "swi XXh" there, I really don't know which of them can be used in thumb and I also don't know if the input and output should be hex numbers.
    Something more about ldmia and stmia:
    For a simple example:
    ........
    ldr r0, ramoffset
    ........
    ldmia r0!, {r2-r6}
    ........

    .align 2
    ramoffset:
    .word 0xXXXXXXXX

    Would the 5 words in r2-r6 be stored into the ram offset loaded previously in r0? If right, how will the 5 words be stored?
    Another question: What is "increment r0"?

    I've read your reply carefully, but still not clear about them, sorry.
     
    Last edited:

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Thank you for your reply. I have now developed a basic idea of swi and I've found something about it in gbatek. But there's many "swi XXh" there, I really don't know which of them can be used in thumb and I also don't know if the input and output should be hex numbers.
    Something more about ldmia and stmia:
    For a simple example:
    ........
    ldr r0, ramoffset
    ........
    ldmia r0!, {r2-r6}
    ........

    .align 2
    ramoffset:
    .word 0xXXXXXXXX

    Would the 5 words in r2-r6 be stored into the ram offset loaded previously in r0? If right, how will the 5 words be stored?
    Another question: What is "increment r0"?

    I've read your reply carefully, but still not clear about them, sorry.

    https://problemkaputt.de/gbatek.htm#biosfunctions
    I think the "h" means halfword (don't quote me on that). You just care about the index value before the "h" anyways, so it doesn't really matter for our uses.

    In your example, ldmia will store r0s contents inside the listed registers. However, r2's contents will not match r3s or any other registers because we're increment r0 = r0 + 4 bytes for each register. Think of it like this:

    Code:
    r0 = pointer to some area in RAM
    rlist = [r2, r3, r4, r5, r6]
    for rX in rlist:
         ldr rX, [r0]
         add r0, r0, #0x4 @next word

    Clearly, rX != r(X +1) because r0 + 4(Y) != r0 +4X for all X, Y EN | X != Y.

    I feel like you're going about this in the wrong order here though. You're trying to understand concepts/commands that (from what I can tell, without offence) are too early for you to be analyzing. Have you read through the beginner/intermediate ASM tutorials around these forums and are able to replicate their teachings in accurate efficiency? I think that completing all, if not most, of the existing tutorials is the first step. These kinds of technical details can probably be avoided during the early stage. Look at SWI after you've learned function calls in ASM and function calls in the ROM in general. Look at LDMIA/STMIA after you've understood how looping works in ASM and perhaps the difference between loading contents of an address vs applying math to the address itself (they're two simple things that I notice are often leading to confusions). Basically, stick to the basics before attempting the understand harder things.
     

    jiangzhengwenjzw

    now working on katam
  • 181
    Posts
    11
    Years
    • Seen today
    https://problemkaputt.de/gbatek.htm#biosfunctions
    I think the "h" means halfword (don't quote me on that). You just care about the index value before the "h" anyways, so it doesn't really matter for our uses.

    In your example, ldmia will store r0s contents inside the listed registers. However, r2's contents will not match r3s or any other registers because we're increment r0 = r0 + 4 bytes for each register. Think of it like this:

    Code:
    r0 = pointer to some area in RAM
    rlist = [r2, r3, r4, r5, r6]
    for rX in rlist:
         ldr rX, [r0]
         add r0, r0, #0x4 @next word

    Clearly, rX != r(X +1) because r0 + 4(Y) != r0 +4X for all X, Y EN | X != Y.

    I feel like you're going about this in the wrong order here though. You're trying to understand concepts/commands that (from what I can tell, without offence) are too early for you to be analyzing. Have you read through the beginner/intermediate ASM tutorials around these forums and are able to replicate their teachings in accurate efficiency? I think that completing all, if not most, of the existing tutorials is the first step. These kinds of technical details can probably be avoided during the early stage. Look at SWI after you've learned function calls in ASM and function calls in the ROM in general. Look at LDMIA/STMIA after you've understood how looping works in ASM and perhaps the difference between loading contents of an address vs applying math to the address itself (they're two simple things that I notice are often leading to confusions). Basically, stick to the basics before attempting the understand harder things.

    Haha, thank you for your reply.
    I think you misunderstood my meaning. (Maybe that's because I don't use English in my daily life so I cannot convey my meaning)

    For the swi case, I thought that h means hex as no$gba showed "h" this when debugging..... My question is that do all these functions all available in thumb? (Maybe I didn't convey my meaning clearly)

    For the basic things, I've read JPAN's tutorial and some other tutorials (some not in this forum). I think I've known some basic things and I can write some functions in the ROM and as I've read JPAN's tutorial, I know how loop works from his simple "deleting pokemon" function. (Of course, I'm still a newbie, but not such new XD)

    For ldmia and stmia, I think I know it this time.
    Still for this example:
    Code:
    ........
    ldr r0, ramoffset
    ........
    ldmia r0!, {r2-r6}
    ........
    
    .align 2
    ramoffset:
    .word 0x02000000

    If at 0x02000000 stores [WORD 1][WORD 2]...[WORD 5]...
    then r2 will be WORD 1
    ......
    r6 will be WORD 5

    RIGHT?
     

    Blah

    Free supporter
  • 1,924
    Posts
    11
    Years
    Haha, thank you for your reply.
    I think you misunderstood my meaning. (Maybe that's because I don't use English in my daily life so I cannot convey my meaning)

    For the swi case, I thought that h means hex as no$gba showed "h" this when debugging..... My question is that do all these functions all available in thumb? (Maybe I didn't convey my meaning clearly)

    For the basic things, I've read JPAN's tutorial and some other tutorials (some not in this forum). I think I've known some basic things and I can write some functions in the ROM and as I've read JPAN's tutorial, I know how loop works from his simple "deleting pokemon" function. (Of course, I'm still a newbie, but not such new XD)

    For ldmia and stmia, I think I know it this time.
    Still for this example:
    Code:
    ........
    ldr r0, ramoffset
    ........
    ldmia r0!, {r2-r6}
    ........
    
    .align 2
    ramoffset:
    .word 0x02000000

    If at 0x02000000 stores [WORD 1][WORD 2]...[WORD 5]...
    then r2 will be WORD 1
    ......
    r6 will be WORD 5

    RIGHT?
    All of them are available in thumb mode unless stated otherwise (divARM for example is ARM obviously, and the ones marked as NDS aren't GBA)
    Actually that's not what happens in the ldmia still. It's like a looped ldr. The word sequence at the RAM offset (in r0) is being stored in the registers in the Rlist, ldr != str.

    I was just suspicious that you were curious about things, while not understanding the basics. If you've read tutorials, then you can dismiss my random suspicions :P
     
    Status
    Not open for further replies.
    Back
    Top