• 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.

How to use custom ASM routines in move animation scripts

58
Posts
8
Years
    • Seen Jan 7, 2017

    How to use custom ASM routines in move animation scripts (Part 1)

    As more and more people are interested in the move animation scripts, I'm determined to write a simple tutorial on command "03" in animation scripts. As for now, almost all hackers uses built-in functions. However, using custom routines is quite easy so I'm going to explain it as it seems that no one wants to do this kind of boring work.
    This tutorial require basic ASM knowledge.

    You'd better read these threads before going on.
    http://www.pokecommunity.com/showthread.php?t=281520
    http://www.pokecommunity.com/showthread.php?t=354621
    http://www.pokecommunity.com/showthread.php?t=238937

    Before we start, let's get some basic information of the script:

    1. Firstly let's take a look at the script for the move "Slash":
    RAW version:
    Code:
    00 C7 27 02 A4 35 3E 08 82 03 01 00 F8 FF F8 FF 19 81 00 3F 04 04 02 A4 35 3E 08 82 03 01 00 08 00 F8 FF 03 1D 8B 09 08 02 05 01 00 04 00 00 00 12 00 01 00 19 81 00 3F 05 08
    Readable format:
    Code:
    #org @slash
    loadgraphic 0x27c7 //slash
    loadobjtemplate 0x83e35a4 0x82 0x3 0x1 0xfff8 0x0
    sound 0x81 0x3f
    pause 0x4
    loadobjtemplate 0x83e35a4 0x82 0x3 0x1 0x8 0x0
    launchtask 0x8098b1d 0x2 0x5 0x1 0x4 0x0 0x12 0x1
    sound 0x81 0x3f
    waitanimation
    end

    2. A quick note on some information:
    Code:
    cmd2_args: used by callback_80A5940 in objtemplate_83e35a4
    arg1_0x1: indicating defender //see knizz's db for more information
    arg2_0xfff8: x_coordinate_offset
    arg3_0x0: y_coordinate_offset
    As you can see, the 3 arguments of the "02" cmd are used by the built in callback function.
    If you define a new template, you can change the callback function to your custom one.
    The function is as such, which is easy for understanding:
    Code:
    callback_80A5940:
    ROM:080A5940 sub_80A5940:                            @ DATA XREF: ROM:stru_83E35A4o
    ROM:080A5940                 PUSH    {R4-R6,LR}
    ROM:080A5942                 MOVS    R5, R0
    ROM:080A5944                 LDR     R6, =ma02_t0_02037F02 @ 0-attacker
    ROM:080A5944                                         @ 1-defender
    ROM:080A5944                                         @ 2-other attacker
    ROM:080A5944                                         @ 3-other defender
    ROM:080A5946                 MOVS    R1, #0
    ROM:080A5948                 LDRSH   R0, [R6,R1]
    ROM:080A594A                 CMP     R0, #0
    ROM:080A594C                 BNE     loc_80A595C
    ROM:080A594E                 LDR     R4, =b_anim_attacker
    ROM:080A5950                 B       loc_80A595E
    ROM:080A5950 @ ---------------------------------------------------------------------------
    ROM:080A5952                 .align 4
    ROM:080A5954 off_80A5954:    .long ma02_t0_02037F02  @ DATA XREF: sub_80A5940+4r
    ROM:080A5954                                         @ 0-attacker
    ROM:080A5954                                         @ 1-defender
    ROM:080A5954                                         @ 2-other attacker
    ROM:080A5954                                         @ 3-other defender
    ROM:080A5958 off_80A5958:    .long b_anim_attacker   @ DATA XREF: sub_80A5940+Er
    ROM:080A595C @ ---------------------------------------------------------------------------
    ROM:080A595C
    ROM:080A595C loc_80A595C:                            @ CODE XREF: sub_80A5940+Cj
    ROM:080A595C                 LDR     R4, =b_anim_defender
    ROM:080A595E
    ROM:080A595E loc_80A595E:                            @ CODE XREF: sub_80A5940+10j
    ROM:080A595E                 LDRB    R0, [R4]
    ROM:080A5960                 MOVS    R1, #2
    ROM:080A5962                 BL      sub_8074480
    ROM:080A5966                 LSLS    R0, R0, #0x18
    ROM:080A5968                 LSRS    R0, R0, #0x18
    ROM:080A596A                 LDRH    R1, [R6,#2]
    ROM:080A596C                 ADDS    R0, R0, R1
    ROM:080A596E                 STRH    R0, [R5,#obj.pos_1]
    ROM:080A5970                 LDRB    R0, [R4]
    ROM:080A5972                 MOVS    R1, #3
    ROM:080A5974                 BL      sub_8074480
    ROM:080A5978                 LSLS    R0, R0, #0x18
    ROM:080A597A                 LSRS    R0, R0, #0x18
    ROM:080A597C                 LDRH    R6, [R6,#4]
    ROM:080A597E                 ADDS    R0, R0, R6
    ROM:080A5980                 STRH    R0, [R5,#obj.pos_1.y]
    ROM:080A5982                 MOVS    R0, #0
    ROM:080A5984                 STRH    R0, [R5,#obj.private0]
    ROM:080A5986                 STRH    R0, [R5,#obj.private1]
    ROM:080A5988                 LDR     R1, =(sub_80A5A8C+1)
    ROM:080A598A                 MOVS    R0, R5
    ROM:080A598C                 BL      oamt_set_x3A_32
    ROM:080A5990                 LDR     R0, =(sub_8074F6C+1)
    ROM:080A5992                 STR     R0, [R5,#obj.callback]
    ROM:080A5994                 POP     {R4-R6}
    ROM:080A5996                 POP     {R0}
    ROM:080A5998                 BX      R0
    ROM:080A5998 @ End of function sub_80A5940
    ROM:080A5998
    ROM:080A5998 @ ---------------------------------------------------------------------------
    ROM:080A599A                 .align 4
    ROM:080A599C off_80A599C:    .long b_anim_defender   @ DATA XREF: sub_80A5940:loc_80A595Cr
    ROM:080A59A0 off_80A59A0:    .long sub_80A5A8C+1     @ DATA XREF: sub_80A5940+48r
    ROM:080A59A4 off_80A59A4:    .long sub_8074F6C+1     @ DATA XREF: sub_80A5940+50r

    Therefore, it's quite straight forward for how to change the x&y offset of the object. As you can see, the EWRAM address 0x2037F02 contains the arguments. As you can imagine, it adds the arguments (I'm speaking of 0xfff8 & 0) to the initial location of the object, which is defined by the first arg (0x1). Here it's 0x1, which means that it's on the defender of the move.

    3. obj_anim_scr_data defined for the object of "slash" (ripped from template):
    Code:
    00 00 04 00 10 00 04 00 20 00 04 00 30 00 04 00 FF FF 00 00
    readable format:
    Code:
    firstframe 0x4
    secondframe 0x4
    thirdframe 0x4
    fourthframe 0x4
    end 0x0
    As you know, the objects are in size of 32x32 pixels, so in obj tiles, 0x10 is for one picture.

    4. Now we're getting to the main part. The function located at 0x8098b1c is moving the defender. However, we want to customize the movement, so we need to build a new function. As we write the function on our own, arguments are really not necessary. Here's just an example using one argument:
    change this
    Code:
    launchtask 0x8098b1d 0x2 0x5 0x1 0x4 0x0 0x12 0x1
    to this:
    Code:
    launchtask 0x8[offset of the following asm + 1] 0x2 0x1 0x1

    Absolutely, you should adjust the data or the game will freeze:
    New animation:
    Code:
    00 C7 27 02 A4 35 3E 08 82 03 01 00 F8 FF F8 FF 19 81 00 3F 04 04 02 A4 35 3E 08 82 03 01 00 08 00 F8 FF 03 [asm ptr + 1] 02 01 01 00 19 81 00 3F 05 08

    The main part of the original function:
    Code:
    ROM:08098B1C                 PUSH    {R4-R6,LR}
    ROM:08098B1E                 LSLS    R0, R0, #0x18
    ROM:08098B20                 LSRS    R5, R0, #0x18
    ROM:08098B22                 MOVS    R6, #0
    ROM:08098B24                 LDR     R2, =ma02_t0_02037F02 @ 0-attacker
    ROM:08098B24                                         @ 1-defender
    ROM:08098B24                                         @ 2-other attacker
    ROM:08098B24                                         @ 3-other defender
    ROM:08098B26                 LDRH    R0, [R2]        @ 0-attacker
    ROM:08098B26                                         @ 1-defender
    ROM:08098B26                                         @ 2-other attacker
    ROM:08098B26                                         @ 3-other defender
    ROM:08098B28                 MOVS    R3, #0
    ROM:08098B2A                 LDRSH   R1, [R2,R3]
    ROM:08098B2C                 CMP     R1, #3
    ROM:08098B2E                 BGT     loc_8098B48
    ROM:08098B30                 LSLS    R0, R0, #0x18
    ROM:08098B32                 LSRS    R0, R0, #0x18
    ROM:08098B34                 BL      obj_id_for_side_relative_to_move
    ROM:08098B38                 LSLS    R0, R0, #0x18
    ROM:08098B3A                 LSRS    R3, R0, #0x18
    ROM:08098B3C                 CMP     R3, #0xFF
    ROM:08098B3E                 BNE     loc_8098B9E @jump
    ROM:08098B40                 B       loc_8098BA2
    
    ROM:08098B9E loc_8098B9E:                            @ CODE XREF: sub_8098B1C+22j
    ROM:08098B9E                 CMP     R6, #0
    ROM:08098BA0                 BEQ     loc_8098BB4
    
    ROM:08098BB4 loc_8098BB4:                            @ CODE XREF: sub_8098B1C+84j
    ROM:08098BB4                 LDR     R1, =objects
    ROM:08098BB6                 LSLS    R0, R3, #4
    ROM:08098BB8                 ADDS    R0, R0, R3
    ROM:08098BBA                 LSLS    R0, R0, #2
    ROM:08098BBC                 ADDS    R0, R0, R1
    ROM:08098BBE                 LDR     R2, =ma02_t0_02037F02 @ 0-attacker
    ROM:08098BBE                                         @ 1-defender
    ROM:08098BBE                                         @ 2-other attacker
    ROM:08098BBE                                         @ 3-other defender
    ROM:08098BC0                 LDRH    R1, [R2,#(dp09_pos2x__ma02_t2 - ma02_t0_02037F02)]
    ROM:08098BC2                 STRH    R1, [R0,#obj.pos_2]
    ROM:08098BC4                 LDRH    R1, [R2,#(dp09_pos2y__ma02_t3 - ma02_t0_02037F02)]
    ROM:08098BC6                 STRH    R1, [R0,#obj.pos_2.y]
    ROM:08098BC8                 LDR     R1, =tasks
    ROM:08098BCA                 LSLS    R0, R5, #2
    ROM:08098BCC                 ADDS    R0, R0, R5
    ROM:08098BCE                 LSLS    R0, R0, #3
    ROM:08098BD0                 ADDS    R0, R0, R1
    ROM:08098BD2                 STRH    R3, [R0,#8]
    ROM:08098BD4                 LDRH    R1, [R2,#(ma02_t4_02037F08 - ma02_t0_02037F02)]
    ROM:08098BD6                 STRH    R1, [R0,#0xA]
    ROM:08098BD8                 LDRH    R1, [R2,#(ma02_t5_02037F0A - ma02_t0_02037F02)]
    ROM:08098BDA                 STRH    R1, [R0,#0xC]
    ROM:08098BDC                 LDRH    R1, [R2,#(ma02_t5_02037F0A - ma02_t0_02037F02)]
    ROM:08098BDE                 STRH    R1, [R0,#0xE]
    ROM:08098BE0                 LDRH    R1, [R2,#(dp09_pos2x__ma02_t2 - ma02_t0_02037F02)]
    ROM:08098BE2                 STRH    R1, [R0,#0x10]
    ROM:08098BE4                 LDRH    R1, [R2,#(dp09_pos2y__ma02_t3 - ma02_t0_02037F02)]
    ROM:08098BE6                 STRH    R1, [R0,#0x12]
    ROM:08098BE8                 LDR     R1, =(sub_8098C08+1)
    ROM:08098BEA                 STR     R1, [R0]
    ROM:08098BEC                 MOVS    R0, R5
    ROM:08098BEE                 BL      _call_via_r1
    ROM:08098BF2
    ROM:08098BF2 loc_8098BF2:                            @ CODE XREF: sub_8098B1C+8Cj
    ROM:08098BF2                 POP     {R4-R6}
    ROM:08098BF4                 POP     {R0}
    ROM:08098BF6                 BX      R0
    The code is really long and we don't need so many arguments for your own one. So I've written an example:
    Code:
    .thumb
    push {r4, lr}
    add r4, r0, #0 @task_id
    ldr r2, =0x2037f02 @args
    ldrh r0, [r2] @here r0 = 1, for defender
    ldr r3, =0x80749D5
    bl caller_r3
    cmp r0, #0xff
    beq back
    ldr r1, =0x202063C @objects
    mov r2, #0x44
    mul r2, r0
    add r0, r1, r2
    ldr r1, =0x8[offset of this code + 1] + move_function
    mov r3, #0x28
    mul r3, r4
    ldr r2, =0x3005090 @tasks
    add r3, r3, r2
    str r1, [r3]
    str r0, [r3, #8] @task_arg
    mov r2, #0
    strh r2, [r3, #0xc]
    add r0, r4, #0
    bl caller_r1
    b back_2
    back:
    add r0, r4, #0 @task_id
    ldr r3, =0x8072761 @move_task_del
    bl caller_r3
    back_2:
    pop {r4, pc}
    .ltorg
    
    move_function:
    push {r4, lr}
    add r4, r0, #0
    mov r1, #0x28
    mul r1, r0
    ldr r2, =0x3005090
    add r2, r1, r2
    ldrh r0, [r2, #0xc]
    cmp r0, #0
    bne other
    ldr r2, [r2, #8] @task_arg
    ldrh r0, [r2, #0x26] @Y_2
    sub r0, #1
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    strh r0, [r2, #0x26]
    ldrh r0, [r2, #0x24] @X_2
    add r0, #1
    strh r0, [r2, #0x24]
    cmp r0, #0x20
    beq change
    b move_back_2
    
    other:
    ldr r2, [r2, #8] @task_arg
    ldrh r0, [r2, #0x26] @Y_2
    add r0, #1
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    strh r0, [r2, #0x26]
    ldrh r0, [r2, #0x24] @X_2
    sub r0, #1
    strh r0, [r2, #0x24]
    cmp r0, #0
    beq move_back
    b move_back_2
    
    change:
    mov r1, #0x28
    mul r1, r4
    ldr r2, =0x3005090
    add r2, r1, r2
    mov r1, #1
    strh r1, [r2, #0xc]
    b move_back_2
    
    move_back:
    add r0, r4, #0
    ldr r3, =0x8072761 @move_task_del
    bl caller_r3
    
    move_back_2:
    pop {r4, pc}
    
    caller_r1: bx r1
    caller_r3: bx r3

    Change [offset of this code + 1] in the code above to the offset of the code + 1.
    The routine will make the defender move upright, and then downleft.

    As you can see, this is only a small part and I admit that it looks ugly but it's just an example. The main idea of the tutorial is just to provide some information for hackers interested in such things. I may add more information in the future, but I'm busy currently.
    Absolutely, you can read more built-in functions like this to get more information. I know that most people wanna control the custom particles, so why not find a proper move animation script and try it yourself? Gook luck. xD

    Credits: knizz, Touched, Chaos Rush

    Edit: To get more information, please continue reading.
     
    Last edited:
    58
    Posts
    8
    Years
    • Seen Jan 7, 2017

    How to use custom ASM routines in move animation scripts (Part 2)

    5. script for "sword dance":
    RAW:
    Code:
    00 15 27 0A 00 0C 0C 08 19 B8 00 C0 03 7D 90 09 08 02 05 00 00 10 00 06 00 01 00 04 00 02 F8 3B 3E 08 02 02 00 00 00 00 04 16 03 6D 9F 0B 08 02 07 15 27 02 00 02 00 F2 7F 10 00 00 00 00 00 05 0B 00 0D 04 01 08
    readable format:
    Code:
    loadgraphic 0x2715
    cmd0a 0x0
    setbldalpha 0x80c
    sound 0xb8 0xc0
    launchtask 0x809907D 0x2 0x5 0x0 0x10 0x6 0x1 0x4
    loadobjtemplate 0x83e3bf8 0x2 0x2 0x0 0x0
    pause 0x16
    launchtask 0x80b9f6d 0x2 0x7 0x2715 0x2 0x2 0x7ff2 0x10 0x0 0x0
    waitanimation
    clearbitfield 0x0 //attacker
    resetblends
    pause 0x1
    end

    After some testing by using the cmd13 (goto), we can see that the task located at 0x809907C is to move the attacker itself. Therefore, what really matters is these lines:
    Code:
    loadobjtemplate 0x83e3bf8 0x2 0x2 0x0 0x0
    pause 0x16
    launchtask 0x80b9f6d 0x2 0x7 0x2715 0x2 0x2 0x7ff2 0x10 0x0 0x0
    We want to find out how it can make the sword do something.
    The animation script for it is just FF FF 00 00 which has no use.
    However, if we look into the rotscale script in the template, we will find:
    Code:
    10 00 00 01 00 00 00 00 14 00 00 00 00 0C 00 00 00 00 00 00 00 20 00 00 FF 7F 00 00
    In a readable format:
    Code:
    xscale 0x10
    yscale 0x100
    .word 0x0
    //the 3 lines above are just defining the initial status of the sword obj
    xscale 0x14
    yscale 0x0
    pause 0xc
    xscale 0x0
    yscale 0x0
    pause 0x20
    end 0x0
    For example, if we change 0x14 to 0x40, the sword will be a very fat one xD
    Of course, these things are not important and I'm just explaining how the game make the sword change from thin to normal.

    The most important thing is that the tiles_tag & pal_tag of the template is 0x2715 as well! Therefore, why not write a function to get the obj address? Therefore, we will do nothing with the original function!
    Code:
    /*parameter: r0 = tiles_tag
    return value: r0= obj_addr*/
    .thumb
    push {r4-r5, lr}
    add r4, r0, #0
    mov r5, #0
    
    loop: 
    ldr r1, =0x202063C
    mov r2, #0x44
    mul r2, r5
    add r0, r2, r1
    ldr r2, [r0, #0x14]
    ldrh r2, [r2]
    cmp r2, r4
    beq back
    cmp r5, #0x3f
    bne loop
    mov r0, #0
    
    back:
    pop {r4-r5, pc}

    Then I will use the function in step 4 for test :>
    script:
    Code:
    launchtask 0x8[asm offset + 1] 0x2 0x1 0x2715
    Code:
    .thumb
    push {r4, lr}
    add r4, r0, #0
    ldr r0, =0x2037f02
    ldrh r0, [r0]
    bl checker
    cmp r0, #0
    beq main_back
    ldr r1, =0x8[offset of this code + 1] + move_function
    mov r3, #0x28
    mul r3, r4
    ldr r2, =0x3005090 @tasks
    add r3, r3, r2
    str r1, [r3]
    str r0, [r3, #8] @task_arg
    mov r2, #0
    strh r2, [r3, #0xc]
    add r0, r4, #0
    bl caller_r1
    b main_back_2
    
    main_back:
    add r0, r4, #0
    ldr r3, =0x8072761 @move_task_del
    bl caller_r3
    
    main_back_2:
    pop {r4, pc}
    
    checker:
    push {r4-r5, lr}
    add r4, r0, #0
    mov r5, #0
    
    loop: 
    ldr r1, =0x202063C
    mov r2, #0x44
    mul r2, r5
    add r0, r2, r1
    ldr r2, [r0, #0x14]
    ldrh r2, [r2]
    cmp r2, r4
    beq back
    add r5, #1
    cmp r5, #0x40
    bne loop
    mov r0, #0
    
    back:
    pop {r4-r5, pc}
    .ltorg
    
    move_function:
    push {r4, lr}
    add r4, r0, #0
    mov r1, #0x28
    mul r1, r0
    ldr r2, =0x3005090
    add r2, r1, r2
    ldrh r0, [r2, #0xc]
    cmp r0, #0
    bne other
    ldr r2, [r2, #8] @task_arg
    ldrh r0, [r2, #0x26] @Y_2
    sub r0, #1
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    strh r0, [r2, #0x26]
    ldrh r0, [r2, #0x24] @X_2
    add r0, #1
    strh r0, [r2, #0x24]
    cmp r0, #0x20
    beq change
    b move_back_2
    
    other:
    ldr r2, [r2, #8] @task_arg
    ldrh r0, [r2, #0x26] @Y_2
    add r0, #1
    lsl r0, r0, #0x10
    lsr r0, r0, #0x10
    strh r0, [r2, #0x26]
    ldrh r0, [r2, #0x24] @X_2
    sub r0, #1
    strh r0, [r2, #0x24]
    cmp r0, #0
    beq move_back
    b move_back_2
    
    change:
    mov r1, #0x28
    mul r1, r4
    ldr r2, =0x3005090
    add r2, r1, r2
    mov r1, #1
    strh r1, [r2, #0xc]
    b move_back_2
    
    move_back:
    add r0, r4, #0
    ldr r3, =0x8072761 @move_task_del
    bl caller_r3
    
    move_back_2:
    pop {r4, pc}
    .ltorg
    
    caller_r1: bx r1
    caller_r3: bx r3
    Then the sword is moved. However, it is always moved upward after the custom movement. Anyway, we've found a way to get the obj_addr of a particle, congratulations.

    Some information about how to handle the objs:
    0x8468(rotate/scale), 0x83C0(animation)
    the first function can change the rotscale script the obj is using, parameter:
    r0 = obj_addr, r1 = rotscale_anim_index
    the second function can change the animation script the obj is using, parameter:
    r0 = obj_addr, r1 = frame_index_to_set
    before using the second function, you should change its animation index (offset 0x2a) in obj_structure yourself to make it use that specified animation script.
    Credit: Wodka - I found these function usages in his thread.

    6. BG scrolling function:
    As is mentioned in Chaos Rush's original thread, we have a built-in function to scroll the BG. He has combined it with the slash animation to create night slash. Here's the script:
    Code:
    14 00 16 03 2D B8 0B 08 05 04 00 00 00 00 00 00 FF FF 00 C7 27 02 A4 35 3E 08 82 03 01 00 F8 FF 00 00 19 81 00 3F 04 04 02 A4 35 3E 08 82 03 01 00 08 00 00 00 03 1D 8B 09 08 02 05 01 00 04 00 00 00 12 00 01 00 19 81 00 3F 05 0E C7 59 1D 08 08
    readable format:
    Code:
    #org @nightslash
    loadbg 0x0 
    cmd16
    launchtask 0x80BB82D 0x5 0x4 0x0 0x0 0x0 0xffff
    //slashstuff
    call @clearbg
    end
    
    #org @clearbg
    cmd15
    cmd16
    setma02_t0_02037F02 0x7 0xFFFF
    cmd17
    return

    All information lies in the function located at 0x80bb82c and it has 4 args. the first and second arg are the speed of bg scrolling so we can change them to values like 0x20 (20 00).
    However, how does it work? Let's disassemble the function to get some information: (only part of it 'cuz it's long)
    Code:
    ROM:080BB82C                                         @ ROM:081CB120o ...
    ROM:080BB82C                 PUSH    {R4-R6,LR}
    ROM:080BB82E                 LSLS    R0, R0, #0x18
    ROM:080BB830                 LSRS    R6, R0, #0x18
    ROM:080BB832                 MOVS    R0, #0
    ROM:080BB834                 BL      sub_8075458
    ROM:080BB838                 LDR     R0, =(sub_80BB8A4+1) @ funcptr
    ROM:080BB83A                 MOVS    R1, #5          @ priority
    ROM:080BB83C                 BL      task_add
    ROM:080BB840                 LSLS    R0, R0, #0x18
    ROM:080BB842                 LSRS    R5, R0, #0x18
    ROM:080BB844                 LDR     R4, =ma02_t0_02037F02 
    ROM:080BB846                 MOVS    R1, #4
    ROM:080BB848                 LDRSH   R0, [R4,R1]
    ROM:080BB84A                 CMP     R0, #0
    ROM:080BB84C                 BEQ     loc_80BB868 @apparently true
    
    ROM:080BB868                 LDR     R0, =tasks
    ROM:080BB86A                 LSLS    R1, R5, #2
    ROM:080BB86C                 ADDS    R1, R1, R5
    ROM:080BB86E                 LSLS    R1, R1, #3
    ROM:080BB870                 ADDS    R1, R1, R0
    /*codes below are just transfering the arguments to the task arg field*/
    ROM:080BB872                 LDR     R2, =ma02_t0_02037F02
    ROM:080BB874                 LDRH    R0, [R2] @x-speed
    ROM:080BB876                 STRH    R0, [R1,#0xA]
    ROM:080BB878                 LDRH    R0, [R2,#2] @y-speed
    ROM:080BB87A                 STRH    R0, [R1,#0xC]
    ROM:080BB87C                 LDRH    R0, [R2,#6] @0xffff
    ROM:080BB87E                 STRH    R0, [R1,#0xE]
    ROM:080BB880                 LDRH    R0, [R1,#8] @apparently 0 as the task is newly added
    ROM:080BB882                 ADDS    R0, #1
    ROM:080BB884                 STRH    R0, [R1,#8]
    ROM:080BB886                 MOVS    R0, R6
    ROM:080BB888                 BL      move_anim_task_del
    ROM:080BB88C                 POP     {R4-R6}
    ROM:080BB88E                 POP     {R0}
    ROM:080BB890                 BX      R0

    So why not look at the main task?
    Code:
    ROM:080BB8A4 sub_80BB8A4:                            @ DATA XREF: sub_80BB82C+Co
    ROM:080BB8A4                                         @ ROM:off_80BB894o
    ROM:080BB8A4                 PUSH    {R4-R7,LR}
    ROM:080BB8A6                 LSLS    R0, R0, #0x18
    ROM:080BB8A8                 LSRS    R5, R0, #0x18
    ROM:080BB8AA                 LDR     R0, =tasks
    ROM:080BB8AC                 LSLS    R1, R5, #2
    ROM:080BB8AE                 ADDS    R1, R1, R5
    ROM:080BB8B0                 LSLS    R1, R1, #3
    ROM:080BB8B2                 ADDS    R1, R1, R0
    ROM:080BB8B4                 LDRH    R3, [R1,#0xA] @x-speed
    ROM:080BB8B6                 LDRH    R0, [R1,#0x1C]
    ROM:080BB8B8                 ADDS    R3, R3, R0
    ROM:080BB8BA                 MOVS    R4, #0
    ROM:080BB8BC                 MOV     R12, R4
    ROM:080BB8BE                 STRH    R3, [R1,#0x1C]
    ROM:080BB8C0                 LDRH    R2, [R1,#0xC] @y-speed
    ROM:080BB8C2                 LDRH    R7, [R1,#0x1E]
    ROM:080BB8C4                 ADDS    R2, R2, R7
    ROM:080BB8C6                 STRH    R2, [R1,#0x1E]
    ROM:080BB8C8                 LDR     R6, =vblank_cb_battle_BG3HOFS
    ROM:080BB8CA                 LSLS    R0, R3, #0x10
    ROM:080BB8CC                 ASRS    R0, R0, #0x18
    ROM:080BB8CE                 LDRH    R4, [R6]
    ROM:080BB8D0                 ADDS    R0, R0, R4
    ROM:080BB8D2                 STRH    R0, [R6] @changing_offset_horizontal
    ROM:080BB8D4                 LDR     R4, =vblank_cb_battle_BG3VOFS
    ROM:080BB8D6                 LSLS    R0, R2, #0x10
    ROM:080BB8D8                 ASRS    R0, R0, #0x18
    ROM:080BB8DA                 LDRH    R7, [R4]
    ROM:080BB8DC                 ADDS    R0, R0, R7
    ROM:080BB8DE                 STRH    R0, [R4] @changing_offset_vertical
    ROM:080BB8E0                 MOVS    R0, #0xFF
    ROM:080BB8E2                 ANDS    R3, R0
    ROM:080BB8E4                 STRH    R3, [R1,#0x1C]
    ROM:080BB8E6                 ANDS    R2, R0
    ROM:080BB8E8                 STRH    R2, [R1,#0x1E]
    ROM:080BB8EA                 LDR     R0, =ma02_t0_02037F02
    ROM:080BB8EC                 MOVS    R3, #0xE
    ROM:080BB8EE                 LDRSH   R2, [R0,R3] @counter
    ROM:080BB8F0                 MOVS    R7, #0xE
    ROM:080BB8F2                 LDRSH   R0, [R1,R7] @0xffff
    ROM:080BB8F4                 CMP     R2, R0
    ROM:080BB8F6                 BNE     loc_80BB90A
    /*codes below are just finishing the scrolling*/
    ROM:080BB8F8                 MOV     R0, R12 @0
    ROM:080BB8FA                 STRH    R0, [R6]
    ROM:080BB8FC                 STRH    R0, [R4]
    ROM:080BB8FE                 MOVS    R0, #1
    ROM:080BB900                 BL      sub_8075458 @something like bg_execute? 
    ROM:080BB904                 MOVS    R0, R5
    ROM:080BB906                 BL      task_del
    ROM:080BB90A
    ROM:080BB90A loc_80BB90A:                            @ CODE XREF: sub_80BB8A4+52j
    ROM:080BB90A                 POP     {R4-R7}
    ROM:080BB90C                 POP     {R0}
    ROM:080BB90E                 BX      R0
    ROM:080BB90E @ End of function sub_80BB8A4

    Therefore, the key of bg scrolling is to change vblank_cb_battle_BG3HOFS and vblank_cb_battle_BG3VOFS, which is located at 0x2022980 and 0x2022982. (Around these offsets there exist other things used in battle like the hof and vof of bg0, 1, 2 and the size of the two windows) It will be quite easy to write a custom function to make a custom bg scrolling effect. Instead of the original one, which can only make it scroll in one direction, you can make some complex scrolling now! I think these things are quite simple and you can do it yourself so I won't write an example for this.

    So i think that's all for this tutorial, and I won't add anything to it unless there exist errors like typos in it. If you find something interesting and useful, please post it here and I will add it to my post.
     
    Last edited:
    Back
    Top