View Full Version : Research: Scripts

January 6th, 2010, 2:34 PM
struct Script{
u8 SubScriptsCount;
u8 Continue;
u16 ifFlag;
u32 THUMBRoutine;
u32 NextOffset;
u32 ReturnOffsets[20];
u32 CommandTablePointer;
u32 LastCommandPointer;
u32 MemoryBanks[4];

SubScriptsCount: Number of scripts 'called' by "call" or "callstd".
Continue: If 0 the script ends, else the script continues.
ifFlag: Results of comparisons(compare, checkflags, etc). Used with the 'if' statements(0 = '<' || 1 = '=' || 2 = '>').
THUMBRoutine: A THUMB Routine?
NextOffset: Offset of next byte to be read.
ReturnOffsets: Array of return offsets(command 'return').
CommandTablePointer: Pointer to command table.
LastCommandPointer: Pointer to the last existing one.
MemoryBanks: Places to store data(loadpointer aka messagebox).

The script structure is located in RAM.
In BPRE, is located in 0x03000EB0.
In BPEE, 0x03000E40

I'm not too sure what the thumb routine do, because I did not get to check it out.

Each command is represented by one byte.
Each byte read is added '1'(one) to NextOffset.

"Script Routine":

ROM:08069804 @ ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
ROM:08069804 Parameters: r0 = Script struct Pointer
ROM:08069804 Scripts: @ CODE XREF: sub_8069AA8+14p
ROM:08069804 PUSH {R4,LR}
ROM:08069806 ADD R4, R0, #0
ROM:08069808 LDRB R0, [R4,#1] @Script.Continue
ROM:0806980A CMP R0, #1
ROM:0806980C BEQ loc_8069842
ROM:0806980E CMP R0, #1
ROM:08069810 BGT loc_8069818
ROM:08069812 CMP R0, #0
ROM:08069814 BEQ loc_8069834
ROM:08069816 B loc_806987A
ROM:08069818 @ ---------------------------------------------------------------------------
ROM:08069818 loc_8069818: @ CODE XREF: Scripts+Cj
ROM:08069818 CMP R0, #2
ROM:0806981A BNE loc_806987A
ROM:0806981C LDR R0, [R4,#4] @Script.THUMBRoutine
ROM:0806981E CMP R0, #0
ROM:08069820 BEQ loc_806983E
ROM:08069822 BL bx_r0
ROM:08069826 LSL R0, R0, #0x18
ROM:08069828 LSR R0, R0, #0x18
ROM:0806982A CMP R0, #1
ROM:0806982C BNE loc_806987A
ROM:0806982E STRB R0, [R4,#1] @Script.Continue
ROM:08069830 B loc_806987A
ROM:08069832 @ ---------------------------------------------------------------------------
ROM:08069832 loc_8069832: @ CODE XREF: Scripts+42j
ROM:08069832 STRB R2, [R4,#1] @Script.Continue
ROM:08069834 loc_8069834: @ CODE XREF: Scripts+10j
ROM:08069834 MOV R0, #0
ROM:08069836 B loc_806987C
ROM:08069838 @ ---------------------------------------------------------------------------
ROM:08069838 loc_8069838: @ CODE XREF: Scripts+64j
ROM:08069838 MOV R0, #0
ROM:0806983A STRB R0, [R4,#1] @Script.Continue
ROM:0806983C B loc_806987C
ROM:0806983E @ ---------------------------------------------------------------------------
ROM:0806983E loc_806983E: @ CODE XREF: Scripts+1Cj
ROM:0806983E MOV R0, #1
ROM:08069840 STRB R0, [R4,#1] @Script.Continue
ROM:08069842 loc_8069842: @ CODE XREF: Scripts+8j
ROM:08069842 @ Scripts+74j
ROM:08069842 LDR R2, [R4,#8] @Script.NextOffset
ROM:08069844 CMP R2, #0
ROM:08069846 BEQ loc_8069832
ROM:08069848 LDR R0, =0x83A7244
ROM:0806984A LDR R0, [R0] @0x0
ROM:0806984C CMP R2, R0
ROM:0806984E BNE loc_8069858
ROM:08069850 loc_8069850: @ CODE XREF: Scripts+4Ej
ROM:08069850 SWI 2
ROM:08069852 B loc_8069850
ROM:08069852 @ ---------------------------------------------------------------------------
ROM:08069854 off_8069854: .long unk_83A7244 @ DATA XREF: Scripts+44r
ROM:08069858 @ ---------------------------------------------------------------------------
ROM:08069858 loc_8069858: @ CODE XREF: Scripts+4Aj
ROM:08069858 LDRB R1, [R2]
ROM:0806985A ADD R0, R2, #1
ROM:0806985C STR R0, [R4,#8]
ROM:0806985E LSL R1, R1, #2
ROM:08069860 LDR R0, [R4,#0x5C] @Script.CommandTablePointer
ROM:08069862 ADD R1, R0, R1
ROM:08069864 LDR R0, [R4,#0x60] @Script.LastCommandPointer
ROM:08069866 CMP R1, R0
ROM:08069868 BCS loc_8069838
ROM:0806986A LDR R1, [R1]
ROM:0806986C ADD R0, R4, #0
ROM:0806986E BL sub_81E3BAC
ROM:08069872 LSL R0, R0, #0x18
ROM:08069874 LSR R0, R0, #0x18
ROM:08069876 CMP R0, #1
ROM:08069878 BNE loc_8069842
ROM:0806987A loc_806987A: @ CODE XREF: Scripts+12j
ROM:0806987A @ Scripts+16j ...
ROM:0806987A MOV R0, #1
ROM:0806987C loc_806987C: @ CODE XREF: Scripts+32j
ROM:0806987C @ Scripts+38j
ROM:0806987C POP {R4}
ROM:0806987E POP {R1}
ROM:08069880 BX R1
ROM:08069880 @ End of function Scripts
ROM:08069880 @ ---------------------------------------------------------------------------
ROM:08069882 .byte 0
ROM:08069883 .byte 0

Now to 'call' a script from an ASM routine, you should do something like:

push {r0, r4, lr}
ldr r0,= 0x03000EB0 @Script Struct
mov r4, #1
strb r4, [r0,#1] @Script.Continue
ldr r4,= 0x08165862 @Custon script offset
str r4, [r0,#8] @Script.NextOffset
bl CallScript
pop {r0, r4}
pop {r1}
bx r1

ldr r4,= 0x08069805 @Script Routine (BPGE)
bx r4

I think this "answers" a question of JPAN, and some "The Follow Me Script" topic.

(ultimate goal) It is possible, but how can we create items that execute scripts.

I hope this helps someone with something. :D

And I hope someone they can collaborate to add more things in the 'article'. :P

January 7th, 2010, 12:52 PM
Interesting find.. Mastermind_X told me about this a long time ago, but I never understood it lol so I just knew of executing scripts without setting the script structure. Here's Ruby's:
Script Structure Location - 0x030006A4
Will post more later.

January 7th, 2010, 2:24 PM
I once started a documentation of it. But it never was finished. The first pre-alpha-draft can be found here:


September 10th, 2012, 12:18 AM
Whenever i start on doing a Script I get bored partly into it.
I know it's important

Full Metal
September 10th, 2012, 4:19 AM
Thank you! With this I might be able to find the Level-Script loader, and from there try and allow multiple level-scripts of the same type to function. :)

September 29th, 2012, 8:21 AM
About the Follow-Me..
I made a now finished Script of it.
You can have your Pikachu all Maps behind you and with the getplayerpos you can also
have "two" scripts at once^^

September 29th, 2012, 4:13 PM
About the Follow-Me..
I made a now finished Script of it.
You can have your Pikachu all Maps behind you and with the getplayerpos you can also
have "two" scripts at once^^
Mind showing us this script? You've piqued my curiosity.