View Single Post
  #168    
Old September 26th, 2011 (6:42 PM). Edited September 26th, 2011 by Missingyep.
Missingyep Missingyep is offline
     
    Join Date: Jul 2010
    Posts: 275
    Here's some information that may make my previous discovery more useful.

    First, a demonstration.

    Next, the walking subroutine that I used in that demonstration, with comments added. Modifying this should allow for easily-controlled tile-changing-when-stepped on effects.

    Spoiler:
    Code:
    .align 2
    .thumb
    
    SUBR_MAIN:
    push {r4-r7,lr}
    add sp, #-0x4
    lsl r0, r0, #0x18
    lsr r0, r0, #0x18
    ldr r2, EXECUTION_QUEUE
    add r2, r2, #0x8
    lsl r1, r0, #0x2
    add r1, r1, r0
    lsl r1, r1, #0x3
    add r5, r1, r2                     // r5 is the start of roughly 30 bytes of RAM alotted for this functionality
    mov r1, #0x2
    ldsh r0, [r5, r1]                  // we use this as part of a queueing system
    cmp r0, #0x0                       // only happens after switching subroutines with cmda6 (the 30 bytes are cleared)
    beq SUBR_INIT
    cmp r0, #0x1                       // 1 means that we're listening for footsteps
    beq SUBR_STEP
    bgt SUBR_TILE                      // higher values mean we have a tile change queued
    mov r0, #0x1
    strh r0, [r5, #0x2]
    
    SUBR_RTRN:
    add sp, #0x4
    pop {r4-r7}
    pop {pc}
    
    SUBR_INIT:                         // initialize our state data
    mov r4, sp
    add r4, r4, #0x2
    mov r1, r4
    ldr r3, F_GET_COORDS
    bl CALL_R3
    ldrh r2, [sp]
    strh r2, [r5, #0x4] // we
    ldrh r0, [r4]
    strh r0, [r5, #0x6]
    ldr r2, DEFAULT_COLOR
    strh r2, [r5, #0x8]
    mov r2, #0x0
    strh r2, [r5, #0xC]
    mov r2, #0x1
    strh r2, [r5, #0x2]
    b SUBR_RTRN
    
    SUBR_STEP:                         // check if the player's taken a step
    mov r4, sp
    add r4, r4, #0x2
    mov r1, r4
    mov r0, sp
    ldr r3, F_GET_COORDS
    bl CALL_R3
    mov r0, sp                         // compare current coords to logged coords
    ldrh r2, [r0]
    mov r3, #0x0
    ldsh r1, [r0, r3]
    mov r3, #0x4
    ldsh r0, [r5, r3]
    cmp r0, r1
    bne SUBR_STEP_CHECK_SWITCH
    mov r3, #0x0
    ldsh r1, [r4, r3]
    mov r3, #0x6
    ldsh r0, [r5, r3]
    cmp r0, r1
    beq SUBR_RTRN
    b SUBR_STEP_CHECK_SWITCH
    
    SUBR_STEP_CHECK_SWITCH:
    strh r2, [r5, #0x4]                // log the new coords
    ldrh r0, [r4]
    strh r0, [r5, #0x6]
    mov r0, sp
    mov r3, #0x0
    ldsh r0, [r0, r3]
    ldsh r1, [r4, r3]
    ldr r3, F_GET_TILE                 // check if the player's standing on one of the "palette" tiles
    bl CALL_R3
    mov r2, #0x0
    ldr r1, BLUE_SWITCH_TILE
    cmp r0, r1
    beq SUBR_STEP_SET_BLUE
    ldr r1, RED_SWITCH_TILE
    cmp r0, r1
    beq SUBR_STEP_SET_RED
    ldr r1, GREEN_SWITCH_TILE
    cmp r0, r1
    beq SUBR_STEP_SET_GREEN
    ldr r1, WHITE_SWITCH_TILE
    cmp r0, r1
    beq SUBR_STEP_SET_WHITE
    b SUBR_STEP_CHECK_CANVAS
    
    SUBR_STEP_SET_BLUE:
    ldr r2, BLUE_CANVAS_TILE
    b SUBR_STEP_SET
    
    SUBR_STEP_SET_RED:
    ldr r2, RED_CANVAS_TILE
    b SUBR_STEP_SET
    
    SUBR_STEP_SET_GREEN:
    ldr r2, GREEN_CANVAS_TILE
    b SUBR_STEP_SET
    
    SUBR_STEP_SET_WHITE:
    ldr r2, WHITE_CANVAS_TILE
    b SUBR_STEP_SET
    
    SUBR_STEP_SET:
    strh r2, [r5, #0x8]                // if so, store their selection (tile ID of color to change to)
    b SUBR_RTRN
    
    SUBR_STEP_CHECK_CANVAS:            // check if standing on a "canvas" tile
    ldr r2, BLUE_CANVAS_TILE
    cmp r0, r2
    beq SUBR_STEP_QUEUE_CANVAS
    ldr r2, RED_CANVAS_TILE
    cmp r0, r2
    beq SUBR_STEP_QUEUE_CANVAS
    ldr r2, GREEN_CANVAS_TILE
    cmp r0, r2
    beq SUBR_STEP_QUEUE_CANVAS
    ldr r2, WHITE_CANVAS_TILE
    cmp r0, r2
    beq SUBR_STEP_QUEUE_CANVAS
    b SUBR_RTRN
    
    SUBR_STEP_QUEUE_CANVAS:
    mov r2, #0x4                       // if so, queue a change
    strh r2, [r5, #0xC]
    mov r0, #0x2
    strh r0, [r5, #0x2]
    ldrh r0, [sp]
    strh r0, [r5, #0xE]
    ldrh r0, [r4]
    strh r0, [r5, #0x10]
    b SUBR_RTRN
    
    SUBR_TILE:
    ldrh r0, [r5, #0xC]
    cmp r0, #0x1                       // we can delay a change by a specific number of frames
    bgt SUBR_TILE_DELAY
    mov r1, sp
    ldrh r0, [r5, #0xE]
    strh r0, [r1]
    mov r4, sp
    add r4, r4, #0x2
    ldrh r0, [r5, #0x10]
    strh r0, [r4]
    mov r0, #0x24                      // the "ice tile just cracked" sound
    ldr r3, F_PLAY_SOUND
    bl CALL_R3
    mov r0, sp
    mov r3, #0x0
    ldsh r0, [r0, r3]
    ldsh r1, [r4, r3]
    ldrh r2, [r5, #0x8]
    ldr r3, F_CHANGE_TILE
    bl CALL_R3
    mov r0, sp
    mov r3, #0x0
    ldsh r0, [r0, r3]
    ldsh r1, [r4, r3]
    ldr r3, F_REPAINT_TILE             // not entirely sure how it works, but it does update the specified tile's entries in graphical memory
    bl CALL_R3
    mov r0, #0x1
    strh r0, [r5, #0x2]
    b SUBR_RTRN
    
    SUBR_TILE_DELAY:
    sub r0, #0x1
    strh r0, [r5, #0xC]
    b SUBR_RTRN
    
    CALL_R3:
    bx r3
    bx lr
    
    .align 2
    F_GET_COORDS:
    .word 0x0805C539
    
    F_GET_TILE:
    .word 0x08058E49
    
    F_PLAY_SOUND:
    .word 0x080722CD
    
    F_CHANGE_TILE:
    .word 0x08058FA5
    
    F_REPAINT_TILE:
    .word 0x0805A8E9
    
    EXECUTION_QUEUE:
    .word 0x03005090
    
    // Everything below here is a tile number in the major and minor tilesets
    // You'd basically use the hex values that AMap shows you when you mouseover a given tile
    DEFAULT_COLOR:
    .word 0x000003F4
    
    BLUE_CANVAS_TILE:
    .word 0x000003EC
    
    RED_CANVAS_TILE:
    .word 0x000003ED
    
    GREEN_CANVAS_TILE:
    .word 0x000003F5
    
    WHITE_CANVAS_TILE:
    .word 0x000003F4
    
    BLUE_SWITCH_TILE:
    .word 0x000003E9
    
    RED_SWITCH_TILE:
    .word 0x000003EA
    
    GREEN_SWITCH_TILE:
    .word 0x000003EB
    
    WHITE_SWITCH_TILE:
    .word 0x000003F1


    The upshot of all of this is that it is now very easy to make polished effects like a floor cracking underneath the player's feet, for example -- complete with sound effects and perhaps even other behaviors.

    That alone could be used for things like unique Gym puzzles. Theoretically, that is just scratching the surface of this functionality's potential, however. Remember that it runs on every frame of animation in which the overworld is being shown and/or processed. In theory, you could do things like timing how long the player stands on a block, or tampering with the movement patterns of an NPC (this runs when you take a step, not when you finish moving, so problems waiting for movement should be few and far between).

    And so this concludes my research on CmdA6.
    Reply With Quote