diff --git a/src/HexManiac.WPF/HexManiac.WPF.csproj b/src/HexManiac.WPF/HexManiac.WPF.csproj
index aee0044f..4f6d9fe8 100644
--- a/src/HexManiac.WPF/HexManiac.WPF.csproj
+++ b/src/HexManiac.WPF/HexManiac.WPF.csproj
@@ -40,6 +40,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/src/HexManiac.WPF/Scripts/ability_type_swaps.hma b/src/HexManiac.WPF/Scripts/ability_type_swaps.hma
index 08fb6a60..e741a810 100644
--- a/src/HexManiac.WPF/Scripts/ability_type_swaps.hma
+++ b/src/HexManiac.WPF/Scripts/ability_type_swaps.hma
@@ -1,5 +1,4 @@
# Introduce a new ability type-swap table.
-# FireRed Only
# Abilities in this table will change moves of one type to another
# Example: Pixilate
@@ -20,10 +19,21 @@
-# main routine
+# mark the divide method
+@!game(AXVE0) @1E0868 @!game(AXPE0) @1E07F8
+@!game(AXVE1) @1E0880 @!game(AXPE1) @1E0810
+@!game(BPRE0) @1E4018 @!game(BPGE0) @1E3FF4
+@!game(BPRE1) @1E4088 @!game(BPGE1) @1E4064
+@!game(BPEE0) @2E7540
+@!game(All) ^thumb.divide
+
+
+
+# main routine (FR/LG/Emerald)
+@!game(BPRE0_BPGE0_BPRE1_BPGE1_BPEE0)
@thumb.abilities.typeswaps(B0) .thumb
@ from original script
- push {r4-r7, lr}
+ push {r4-r7, lr} # TODO in ruby, we push 6 registers, not just 4
sub sp, #16
@ r0 = current pokemon ability
@@ -79,7 +89,7 @@
ldr r0, [r0, #0]
strb r3, [r0, #19] @ gBattleStruct->dynamicMoveType = data.abilities.typeswaps[i].change | 0x40
checkInitialDynamicBasePower:
- ldr r5, =0x02023F50 @ gDynamicBasePower
+ ldr r5, [pc, ]
ldrh r0, [r5, #0]
cmp r0, #0
bne
@@ -100,28 +110,141 @@
strh r0, [r5, #0] @ gDynamicBasePower = gDynamicBasePower * scale / 100
end:
@ from original script
- ldr r4, =0x02023DDE
- ldr r5, =0x02023D6C
+ ldr r4, [pc, ]
+ ldr r5, [pc, ]
@ return to original script
- ldr r0, =+8
+ ldr r0, = @ damagecalc
bx r0
- gBattleMons: .word 0x02023BE4
- gBattlerAttacker: .word 0x02023D6B
- gCurrentMove: .word 0x02023D4A
- gBattleStruct: .word 0x02023FE8
divide:
- ldr r2, =<1E4018>+1
+ ldr r2, =
bx r2
+ gBattleMons: .word 0x02023BE4
+ gCurrentMove: .word 0x02023D4A
+ gBattlerAttacker: .word 0x02023D6B
+ gBattlerTarget: .word 0x02023D6C
+ gSideStatuses: .word 0x02023DDE
+ gDynamicBasePower: .word 0x02023F50
+ gBattleStruct: .word 0x02023FE8
.end
+@!game(BPEE0)
+@thumb.abilities.typeswaps+8C .thumb
+ gBattleMons: .word 0x02024084
+ gCurrentMove: .word 0x020241EA
+ gBattlerAttacker: .word 0x0202420B
+ gBattlerTarget: .word 0x0202420C
+ gSideStatuses: .word 0x0202428E
+ gDynamicBasePower: .word 0x02024400
+ gBattleStruct: .word 0x0202449C
+.end
+
+
+
+# main routine (Ruby/Sapphire) (separate because R/S version uses more stack)
+@!game(AXVE0_AXPE0_AXVE1_AXPE1)
+@thumb.abilities.typeswaps(B0) .thumb
+ @ from original script
+ push {r4-r7, lr}
+ mov r7, r9
+ mov r6, r8
+ push {r6-r7}
+
+ @ r0 = current pokemon ability
+ @ r1 = current pokemon move type
+ @ r2 = typeswap ability table
+ @ r3 = index
+ @ loop until -1
+ @ compare pokemon ability (r0) vs first 2 bytes
+ @ when match:
+ @ compare pokemon type (r1) vs next byte
+ @ when match:
+ @ set dynamic type as 0x40 + target type (last byte)
+
+ @ r0 = gBattleMons[gBattlerAttacker].ability
+ ldr r0, [pc, ]
+ ldr r1, [pc, ]
+ ldrb r1, [r1, #0]
+ mov r2, 0x58 @ sizeof(BattlePokemon)
+ mul r1, r2
+ add r1, #0x20 @ BattlePokemon.ability
+ ldrb r0, [r0, r1] @ r0 = gBattleMons[gBattlerAttacker].ability
+
+ @ r1 = gBattleMoves[gCurrentMove].type
+ ldr r1, =
+ ldr r2, [pc, ]
+ ldrh r2, [r2, #0]
+ mov r3, #12 @ sizeof(BattleMove)
+ mul r2, r3
+ add r2, #2 @ BattleMove.type (change to 3 if you've done move expansion)
+ ldrb r1, [r1, r2] @ r1 = gBattleMoves[gCurrentMove].type
+
+ @ r2 = pixilate ability table + index*4 (4 is the size of the table elements)
+ ldr r2, =
+ sub r2, #4
+
+ loop:
+ add r2, #4
+ ldrh r3, [r2, #0] @ r3 = FFFF if we're at the end of the table
+ ldr r4, =0xFFFF
+ cmp r3, r4 @ ability == FFFF
+ beq
+ ldrb r3, [r2, #0] @ r3 = the ability from the table
+ cmp r0, r3 @ ability == gBattleMons[gBattlerAttacker].ability
+ bne
+ ldrb r3, [r2, #1] @ r3 = the source type from the table
+ cmp r1, r3
+ bne
+ setDynamicMoveType:
+ ldrb r3, [r2, #2] @ r3 = the target type
+ mov r0, #0x40
+ orr r3, r0
+ ldr r0, [pc, ]
+ strb r3, [r0, #0] @ gBattleStruct->dynamicMoveType = data.abilities.typeswaps[i].change | 0x40
+ checkInitialDynamicBasePower:
+ ldr r5, [pc, ]
+ ldrh r0, [r5, #0]
+ cmp r0, #0
+ bne
+ setInitialDynamicBasePower:
+ ldr r0, [pc, ]
+ ldrh r0, [r0, #0]
+ mov r1, #12 @ sizeof(BattleMove)
+ mul r0, r1
+ add r0, #1 @ BattleMove.power (change to 2 if you've done move expansion)
+ ldr r1, =
+ ldrb r0, [r1, r0] @ r0 = gBattleMoves[gCurrentMove].power
+ strh r0, [r5, #0] @ gDynamicBasePower = gBattleMoves[gCurrentMove].power
+ scalePower:
+ ldrb r3, [r2, #3] @ r3 = the target scale
+ mul r0, r3
+ mov r1, #100
+ bl
+ strh r0, [r5, #0] @ gDynamicBasePower = gDynamicBasePower * scale / 100
+ end:
+ @ return to original script
+ ldr r0, = @ damagecalc
+ bx r0
+ divide:
+ ldr r2, =
+ bx r2
+ gBattleMons: .word 0x02024A80
+ gCurrentMove: .word 0x02024BE6
+ gBattlerAttacker: .word 0x02024C07
+ gBattlerTarget: .word 0x02024C08
+ gSideStatuses: .word 0x02024C7A
+ gDynamicBasePower: .word 0x02024DEC
+ gBattleStructDynamicMoveType: .word 0x0201601C
+.end
+@!game(All)
+
# hook atk05_damagecalc
-@01E59C .thumb
+@scripts.battle.thumb/5/code/-1 .thumb
ldr r0, =0
bx r0
.end
-@01E59C+4
+@scripts.battle.thumb/5/code/+3
diff --git a/src/HexManiac.WPF/Scripts/entrance_abilities.hma b/src/HexManiac.WPF/Scripts/entrance_abilities.hma
index 2d31c5f9..840790f7 100644
--- a/src/HexManiac.WPF/Scripts/entrance_abilities.hma
+++ b/src/HexManiac.WPF/Scripts/entrance_abilities.hma
@@ -15,6 +15,8 @@
# gBattleScripting.battler = battler;
# ++effect;
+
+
# setup anchors
@1D927F ^scripts.abilities.entrance.drizzle`bse`
@1D92BF ^scripts.abilities.entrance.sandstream`bse`
@@ -35,6 +37,8 @@
# End Table # 00 00 FF FF FF FF FF FF
@data.abilities.entrance ^data.abilities.entrance[ability:data.abilities.names animation:data.pokemon.moves.names script<`bse`>]!0000
+
+
# main routine
@thumb.abilities.entrance(90) .thumb
push {r0-r7}
@@ -54,7 +58,7 @@
mov r1, r10 @ battler
mov r2, #20
mul r1, r2
- ldr r2, =0x02023ECC @ gSpecialStatuses
+ ldr r2, [pc, ]
add r1, r2
ldrb r3, [r1, #1] @ gSpecialStatuses[battler].0 (entrance is bit 9, previously unused)
lsl r3, r3, #31 @ put bit 9 in the negative bit slot
@@ -66,7 +70,7 @@
orr r3, r5
strb r3, [r1, #1]
@ gBattleStruct->intimidateBattler = battler;
- ldr r0, =0x02023FE8
+ ldr r0, [pc, ]
ldr r0, [r0, #0]
add r0, #216
mov r1, r10 @ battler
@@ -79,14 +83,14 @@
mov r0, r10
mov r1, #1
eor r1, r0
- ldr r0, =0x02023d6c @ gBattlerTarget
+ ldr r0, [pc, ]
strb r1, [r0, #0]
@ gCurrentMove = data.abilities.entrance[i].move // 02023d4a
- ldr r0, =0x02023d4a
+ ldr r0, [pc, ]
ldrh r1, [r4, #2]
strh r1, [r0, #0]
@ gBattleScripting.battler = battler;
- ldr r0, =0x02023FC4 @ gBattleScripting
+ ldr r0, [pc, ]
mov r1, r10
strb r1, [r0, #23] @ .battler
@ ++effect;
@@ -104,6 +108,11 @@
long_branch:
ldr r1, =<01BC25>
bx r1
+ gCurrentMove: .word 0x02023D4A
+ gBattlerTarget: .word 0x02023D6C
+ gSpecialStatuses: .word 0x02023ECC
+ gBattleScripting: .word 0x02023FC4
+ intimidateBattler: .word 0x02023FE8
.end