Thread: Research: Items
View Single Post
Old January 11th, 2010 (7:10 PM).
JPAN JPAN is offline
pokemon rom researcher
    Join Date: Dec 2008
    Posts: 104
    I created an alternative way to run the script through an item, using a really cheap method.
    The return is executed as normally would, and the script starts executing as soon as it leaves the bag.
    But the script it runs is not the one the hacker placed therem but one at a fixed ROM position.
    A "header" that forces the BAG window to close before starting to execute the main code.
    This is the final result asm source file, the version I shall make available in my next hack release:
    .align 2
    /*this is the final result of the first stage of item usage. This code will allow you to run scripts through an item.
    Usage Requirements:
    Compiled key_change_hack;
    compiled special 0xc9 (force key), even if not as a special
    to use:
    1 - place the pointer to this routine in the OW execution word of the item of your choice
    2 - Place the Script pointer in the last word (right next to the name of the next item)
    2.5 - this code does not remove the item, to make it easier to code Key items. Just place in your script somewhere a "removeitem item_num 0x1" to destroy it.
    This has been made to run trainer battles, map display, pokemon selection screen and some specials. seems to work well with all scripting commands.
    New_item_start:  push {r4,lr}
                            ldr r0, RAM_item
                            ldrh r0, [r0]
                            mov r1, #0x2c
                            mul r0, r1
                            ldr r1, item_addr
                            add r0, r0, r1
                            ldr r4, [r0]            /*loads item script*/
                            ldr r2, script_area
                            str r4, [r2]
                            mov r4, #0x5
                            sub r2, #0x1
                            strb r4, [r2]       /*creates a bypass for our real script*/
                            ldr r0, script_pos /*the starter script with the menu shut*/
                            bl script_executer
                            ldr     R1, Script_flag_set
                            mov  R0, #0x1
                            strb R0, [R1]
                            bl bag_exiter
                            pop {r4,pc}
    RAM_item: .word 0x0203ad30
    item_addr: .word 0x083db050
    Script_flag_set: .word 0x03000f9c
    script_executer: ldr r1, exe_addr
                           bx r1
    exe_addr: .word 0x08069AE5
    bag_exiter:  ldr r1, exit_code
                     bx r1
    exit_code: .word 0x080a103d
    script_area: .word 0x0203f3ec
    script_pos: .word 0x00000000
    This script must be compiled and put somewhere in the rom, and the pointer to this placed in script_pos. 
    Compiled version already comes with it compiled, but you need to put the pointer in the 4 zero bytes area in the middle of the code.
    copyvar 0x8012 0x8004
    copyvar 0x8013 0x8005
    setvar 0x8004 0x2
    setvar 0x8005 0x7
    pause 0x16
    special 0xC9 'or callasm @location_you_put_key_presser
    pause 0x1
    copyvar 0x8004 0x8012
    copyvar 0x8005 0x8013
    goto 0x203F3EB
    And the dependencies
    .align 2
    This code will be replacing the two lines at 0x80005e8, the Key loader
    This will, at an end, allow for us to input keys of our own, to create several key-manipulation techniques. Examples:
     key inibition; key replacement.
    to apply, place a bx r0 (00 47) at 0x080005ec and replace the pointer at 0x08000624 to this routine's one.
    Stuff this will do:
    type of change will depend on 0203f4ec contents.
    bit set -> effect
    0 -> change value to and with, so it makes the game believe a certain key is pressed.
           This key value is placed at 0x0203f4de.
    1 -> makes sure a key is not detected. However, that key is allways detected by the key specials.
          Allows you to delete the access to the help menu, or start, etc.
          That keymap must be placed at 0203f4fc.
    2 -> if the player is in the OW, forces the script at 0203f4f4 to run when a key in 
           the position 0x0203f4ee
    Key_wrecker_start: push {r4-r7} 
                               ldr r0, key_addr
                               ldrh r0, [r0]
                               ldr r4, switches
                               ldrb r1, [r4]
                               cmp r1, #0x0
                               beq nothing_to_do
                               bl check_for_script
                               bl check_for_forced
                               bl check_for_cancel
    nothing_to_do:       pop {r4-r7}
                               add r1, r0, #0x0
                               ldr r0, return_place
                               bx r0
    .hword 0x0000
    key_addr: .word 0x04000130
    switches: .word 0x0203f4ec
    return_place: .word 0x080005ef
    check_for_script: push {r0-r1,lr}
                            mov r2, #0x4       /*check for flag*/
                            and r2, r1
                            cmp r2, #0x0
                            beq end_all
                            ldr r5, script_on    /*check if a script is executing*/
                            ldrb r3, [r5]
                            cmp r3, #0x1
                            beq end_all
                            ldrh r2, [r4, #0x2]  /*check if the keys are pressed*/
                            and r2, r0
                            cmp r2, #0x0
                            bne end_all
                            ldr r3, first_function    /*checks if we are in the OW*/
                            ldr r2, [r3]
                            ldr r3, OW_function
                            cmp r2, r3
                            bne end_all
                            mov r2, #0x1 /*if all is ok, run script*/
                            strb r2, [r5]
                            ldr  r0, [r4, #0x8]
                            bl script_executer
    end_all:              pop {r0-r1,pc}
    script_on: .word 0x03000f9c
    first_function: .word 0x03005090
    OW_function: .word 0x08079e0d
    check_for_forced: push {lr}
                             mov r2, #0x1 /*check for flag*/
                             and r2, r1
                             cmp r2, #0x0
                             beq end_all_2
                             ldrb r2, [r4, #0x1] /*check if it should apply it*/
                             cmp r2, #0x0
                             beq end_all_2
                             sub r2, #0x1
                             strb r2, [r4, #0x1] /*updates counter*/
                             sub r4, #0xE
                             ldrh r2, [r4]     /*gets keymap to force*/
                             add r4, #0xe
                             mvn r2, r2
                             and r0, r2         /*keys changed*/
    end_all_2:           pop {pc}
    check_for_cancel: push {lr}
                             mov r2, #0x2 /*check for flag*/
                             and r2, r1
                             cmp r2, #0x0
                             beq end_all_3
                             ldr r2, [r4, #0x10] /*loads key to ignore*/
                             orr r0, r2 /*ignored*/
    end_all_3:           pop {pc}
    script_executer: ldr r1, exe_addr
                           bx r1
    exe_addr: .word 0x08069AE5
    The special is only a setter for the Force B flag. If you understood the above code, you could probably do the same with writebytes
    .align 2
    /*this code forces one keyMap stored on your ROM to run for the asked number of times
    Special c9 receives:
    0x8004 is the keys to set
    0x8005 is the times to set it to
    returns nothing
    Special_c9:  push {r0-r2, lr}
                     ldr r0, key_store_addr
                     ldr r2, var_8004
                     ldrh r1, [r2]
                     strh r1, [r0]
                     ldrh r1, [r2, #0x2]
                     add r0, #0xe
                     strb r1, [r0, #0x1]
                     ldrb r1, [r0]
                     mov r2, #0x1
                     orr r1, r2
                     strb r1, [r0]
                     pop {r0-r2, pc}
    .hword 0x0000
    key_store_addr: .word 0x0203f4de
    var_8004: .word 0x020370c0
    This method will only not work if the player holds down the B button at the same time it exits the bag.
    It could be made certain that B button was not pressed at least for one check, but probably wouldn't be worth it.

    And that's it for Script Items. Just as mentioned in the code above, this is a generic item for any OW activity, and as such, is only guaranteed to work at the Overworld. Next step, finding the battle items code and usages.
    Here are the links for my work

    Currently working on:
    Battle Script Documentation
    Another large project
    Reply With Quote