Binary Hack Research & DevelopmentGot a well-founded knack with your binary Pokémon hacks? Love reverse-engineering them? For the traditional Pokémon ROM hacker, this is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!
Ok, but what are :
_ 0x020247DC
_0x020247DA
_0x02024840
_0x0202483E
Yeah i imagine what they are, but when i tried to find them with the VBA's memory vewer there are just lines of "00".
It is for FireRed, right ?
Ok, but what are :
_ 0x020247DC
_0x020247DA
_0x02024840
_0x0202483E
Yeah i imagine what they are, but when i tried to find them with the VBA's memory vewer there are just lines of "00".
It is for FireRed, right ?
Please forget that post. I was a noob at the time. I'm sorry.
There was only a slight amount of testing done and it doesn't account for any unique causes, so it's probably bugged as hell the Distortion World.
I think, if we swap the Def and the spe Def of the two allies and the two enemies, it will work. The AI will use it very badly, but I'm doing it to make two signature moves (mewtwo and keldeo if I remember). So this move will be used by the user, not the AI.
just I need explanation about "copyarray". What does the "2" do at the end of this command ? I think I have to find free ram space by myself, maybe bsp can't find it alone.
Thanks
#205Link to this post, but load the entire thread.
February 5th, 2015 (5:12 AM).
Trainer 781
Guest
Posts: n/a
Quote:
Originally Posted by Edwearth
I think, if we swap the Def and the spe Def of the two allies and the two enemies, it will work. The AI will use it very badly, but I'm doing it to make two signature moves (mewtwo and keldeo if I remember). So this move will be used by the user, not the AI.
just I need explanation about "copyarray". What does the "2" do at the end of this command ? I think I have to find free ram space by myself, maybe bsp can't find it alone.
Thanks
Only swapping def and sp def won't do the job mate, defense stat changes, plus abilties affecting the defense and sp def also do matter.
Oh, yes sorry I totally forgot abilities and moves like magic mirror. So, is there a function like calculateSpeAttack, calculateDeffense then calculatedamages? :p
What is Asmagix?
I googled ASMAGIX because I was wondering that too, the first page has one link to PC where someone mentions it then says, more serious answer ... . Maybe a troll term?
I googled ASMAGIX because I was wondering that too, the first page has one link to PC where someone mentions it then says, more serious answer ... . Maybe a troll term?
It's a play on the term "ASM" or "Assembly" which is the language the GBA runs on.
It's a play on the term "ASM" or "Assembly" which is the language the GBA runs on.
I know this, but i thought that it is an language between ASM and C or a simplified ASM.
Edit :
I tried something to make the swap. I know it's a wrong way to create the move but I did it like a training.
But when I use it, the effect resets the game.
Here my effect :
Why ? It's my codes ? It's the action which is forbidden ?
Edit : Ok, forget this, i found the solution.
But i have another question ! How to port the callasm command ? I compile the routine with the address 0x02024214 for the scriptlocation. Ok, but I have to repoint and extend the battle script command table to had the new command F9 XX XX XX 08. Where is this table ? And how do you find it ?
There is a problem with the script. When you call the routine, it sets the base damages. But when you calculate damages, it resets the damages to the base damages of the move.
#214Link to this post, but load the entire thread.
February 28th, 2015 (8:28 AM).
Trainer 781
Guest
Posts: n/a
Quote:
Originally Posted by Edwearth
There is a problem with the script. When you call the routine, it sets the base damages. But when you calculate damages, it resets the damages to the base damages of the move.
Could you please be more clear that what are you trying to stay. I am unable to understand.
Could you please be more clear that what are you trying to stay. I am unable to understand.
I call the routine, the base power of the move is set. The calculation is good. So 0x020244E0 (Emerald) takes 0x79 if the enemy is full life.
And then the calculate damage is called, and the base damages are reset. So 0x020244E0 takes 0x1 because in PGE I set the move's base power to 1.
So the damages inflicted to the foe are very low.
#216Link to this post, but load the entire thread.
February 28th, 2015 (10:01 AM).
Trainer 781
Guest
Posts: n/a
Quote:
Originally Posted by Edwearth
I call the routine, the base power of the move is set. The calculation is good. So 0x020244E0 (Emerald) takes 0x79 if the enemy is full life.
And then the calculate damage is called, and the base damages are reset. So 0x020244E0 takes 0x1 because in PGE I set the move's base power to 1.
So the damages inflicted to the foe are very low.
You used the wrong offset for base power, use 0x02024400 instead
It's alright, all of us procrastinate to some extent. By the way since you have added a updated animations section, I might as well share my updated Mud Shot animation:
Step 1: First, add this command in commands.bsh for Battle Script Pro (credit to KDS for first discovering this when he posted his Incinerate script):
Spoiler:
#command removeitem 0x6A 0x1 "Bank" 0x1
(this command to remove items is already in the game so you don't need to add code or anything, it's just unidentified by BSP)
Step 2:
Compile the following table and put it into free space, make sure you take note of the offset you put it in. We'll refer to this table as NATURAL GIFT TABLE:
When compiled, the format of this table will be [XX XX] [YY] [ZZ], with XXXX being the index number of the item, YY being the type that Natural Gift will change into, and ZZ being the base power. This table only covers the berries that are in Gen 3, so if you've added new berries then you'll have to add them into the table. MAKE SURE YOU LEAVE THE FOUR FF BYTES AT THE END, DO NOT OVERWRITE IT. (or change them to FE bytes, and in Step 3 modify the line "mov r4, 0xFF" to "mov r4, 0xFE").
Step 3:
Insert this routine into free space, and take note of its offset. We'll refer to this as ASM ROUTINE 1:
Spoiler:
.text
.align 2
.thumb
.thumb_func
.global test
main:
push {lr}
ldr r0, .UserBank
ldr r1, .BattleData
ldrb r0, [r0]
mov r2, #0x58
mul r2, r0
add r1, #0x2E
add r1, r2
ldrh r0, [r1] /*r0 should now have held item. r1 is the RAM offset of the held item*/
cmp r0, #0x0
beq Abort
ldr r2, .NaturalGiftTable
mov r4, #0xFF
Make sure you put in the offset of the Natural Gift table at the last line.
Step 4:
Now, insert this routine into free space as well, and take note of its offset. We'll refer to this as ASM ROUTINE 2:
Spoiler:
.text
.align 2
.thumb
.thumb_func
.global test
GetOpponentType:
push {lr}
ldr r0, .TargetBank
ldr r1, .BattleData
ldrb r0, [r0]
mov r2, #0x58
mul r2, r0
add r1, #0x21
add r1, r2
ldrb r0, [r1] /*r0 should now have opponent Type 1*/
ldrb r2, [r1, #0x1] /*r2 should now have opponent Type 2*/
GetNaturalGiftType:
ldr r1, .MemAddress
ldr r1, [r1]
add r1, #0x13
ldrb r1, [r1] /*r1 should now have modified Natural Gift type*/
ldr r3, .TypeChart
/*check attacking type*/
Check1:
ldrb r4, [r3] /*r4 has Type Chart attacking type*/
ldrb r5, [r3, #0x1] /*r5 has Type Chart defending type*/
ldrb r6, [r3, #0x2] /*r6 has Type Chart effectiveness*/
cmp r4, #0xFE
beq Abort
cmp r1, r4 /*check NG type with Attacking type*/
bne Recheck
cmp r0, r5 /*check opponent Type 1 with Defending type*/
beq Type1Match
cmp r2, r5 /*check opponent Type 2 with Defending type*/
beq OkNowCheckType1
add r3, #0x3
b Check1
OkNowCheckType1:
ldr r3, .TypeChart
b StillCheckinglol
/*we should be here if Type 2 was a match but Type 1 wasn't*/
StillCheckinglol:
ldrb r4, [r3] /*r4 has Type Chart attacking type*/
ldrb r5, [r3, #0x1] /*r5 has Type Chart defending type*/
ldrb r7, [r3, #0x2] /*r7 has Type Chart effectiveness*/
cmp r4, #0xFE
beq SameOutcome
cmp r1, r4 /*check NG type with Attacking type*/
bne Recheck3
cmp r0, r5 /*check opponent Type 1 Defending type*/
beq Type2Match
add r3, #0x3
b Check2
Type1Match:
ldr r3, .TypeChart
b Check2
Check2:
ldrb r4, [r3] /*r4 has Type Chart attacking type*/
ldrb r5, [r3, #0x1] /*r5 has Type Chart defending type*/
ldrb r7, [r3, #0x2] /*r7 has Type Chart effectiveness*/
cmp r4, #0xFE
beq SameOutcome
cmp r1, r4 /*check NG type with Attacking type*/
bne Recheck2
cmp r2, r5 /*check opponent Type 2 Defending type*/
beq Type2Match
add r3, #0x3
b Check2
WeakDamage:
ldr r0, .Outcome
mov r1, #0x04
strb r1, [r0]
b End
NoDamage:
ldr r0, .Outcome
mov r1, #0x08
strb r1, [r0]
b End
SuperDamage:
ldr r0, .Outcome
mov r1, #0x02
strb r1, [r0]
b End
Abort:
End:
pop {r0}
bx r0
.align 2
.Outcome: .word 0x02023DCC .TypeChart: .word 0x0824F050 /*make sure you replace this with the offset of your own type chart*/
.BattleData: .word 0x02023BE4
.TargetBank: .word 0x02023D6C
.MemAddress: .word 0x02023FE8
Note: If you have repointed your type chart, then you will have to put its new offset where I've bolded above.
Here's an explanation as to how this works:
So as you can see, "ASM ROUTINE 1" looks up the custom table we inserted and matches your held item to it (the move will fail if you're not holding an item or if you're holding an item that's not in the table), and then updates the type and base power accordingly. Now, with this routine alone, the damage and type calculations are correct, but the outcome message will always act as a regular move (regular as in not super-effective or not not-very-effective) unless if you don't have an item in the table (then it will just fail), and turns out the reason why is for some reason the outcome RAM offset (02023DCC) wasn't getting updated even though the battle engine should theoretically already have done so (if you have the routine be the first thing in the script). So what "ASM ROUTINE 2" does is that it looks up the type chart and the opponent's types and determines the outcome that way (and yes, I checked and double checked and triple checked with various berry & type combinations, so it works). It wasn't ideal, but it was necessary in order to get the correct message to show up.
"But Chaos, couldn't you just look at how Weather Ball and Hidden Power does it"? Well, I did (for anyone curious, the Weather Ball command's routine is at 0802D090, while the Hidden Power command's routine is at 0802B678), and what both do is that they update the value held by the pointer at 02023FE8(a dynamic memory location) + 0x13, usually the pointer at 02023FE8 leads to 02000010, so the type value is (usually) at 02000023. No matter what I tried with updating that value, it always played the normal hit sound (but would still do more or less damage depending on type, such as Electric type Natural Gift doing more damage to Pidgey than Water type Natural Gift), unless if it was a type immunity in which case it worked as expected. For testing reasons I tried giving a new test move Hidden Power's battle script ID, and turns out the correct sound effect doesn't play either (but it does with Hidden Power itself, even though I gave them the same battle script ID), and turns out the outcome offset was only being updated when using the actual Hidden Power, which leads me to believe that Hidden Power and Weather Ball's move ID's are hard-coded to update the outcome offset. So the whole purpose of "ASM ROUTINE 2" is to circumvent that. "ASM ROUTINE 2" manually looks up the type chart and what outcome it should be, and updates the outcome value at 02023DCC accordingly.
As for the animation, I just use Acid's animation but modified with Sleep Powder's palette, which makes it look a nice greenish-brown color just like the official games.
Power Trick: (note that this doesn't account for Baton Passing like the official games, sorry :P)
Exactly the same as above for Gastro Acid, but use this string and ASM instead.
String:
Quote:
FD 0F 00 E7 EB DD E8 D7 DC D9 D8 00 DD E8 E7 00 BB E8 E8 D5 D7 DF 00 FE D5 E2 D8 00 BE D9 DA D9 E2 E7 D9 AB FF 00
StatusCheck: /*checks if target is readying a status move*/
ldr r0, .TargetBank /*get target slot ID*/
ldrb r0, [r0, #0x0] /*r0 has target bank*/
lsl r0, #0x1
ldr r1, .MovesUsed /*r1 has MovesUsed*/
add r0, r1 /*Target's moved used?*/
ldrh r6, [r0]
ldrh r0, [r0] /*r0 has the move that target is going to use*/
ldr r1, .MoveTable /*r1 now has MoveTable*/
mov r2, #0xc /*move data is C bytes*/
mul r0, r2 /*move ID x C*/
add r0, r1 /*get move offset*/
ldrb r0, [r0, #0xa] /*check the move's class*/
cmp r0, #0x2 /*is it a status move?*/
beq Abort /*if so, the move fails*/ sub r6, #0x1
lsr r6, #0x1
cmp r6, #0xB5 /*fail if Natural Gift*/
beq Abort
OrderCheck:
ldr r0, .TargetBank
ldr r1, .UserBank
ldrb r4, [r0, #0x0] /*put target bank into R4*/
ldrb r5, [r1, #0x0] /*put user bank into R5*/
ldr r1, .TurnOrder /*put turn order offset into R1*/
Loop:
ldrb r2, [r1, #0x0] /*put attacking PKMN into r2*/
cmp r2, r4 /*is the attacking PKMN the target?*/
beq Abort /*if so, quit*/
cmp r2, r5 /*is the attacking PKMN the user?*/
beq End /*if so, attack*/
add r1, #0x1 /*move on to next attacking PKMN*/
b Loop
Abort:
ldr r0, .CurrentScript
ldr r1, .FailScript
str r1, [r0, #0x0]
b End
.UserBank: .word 0x02023D6B
.TargetBank: .word 0x02023D6C
.BattleStruct: .word 0x02023BE4
.MovesUsed: .word 0x02023dc4
.MoveTable: .word 0x08(offset of your move data table)
.CurrentAttack: .word 0x02023D4A
ASM routine 3:
Spoiler:
.text
.align 2
.thumb
.thumb_func
.global test
Main:
push {lr}
ldr r0, .TargetBank /*what slot is the target*/
ldrb r0, [r0, #0x0]
ldr r1, .BattleStruct
mov r2, #0x58
mul r0, r2
add r5, r0, r1
SetStuff:
ldr r0, .TargetBank /*get target slot ID*/
ldrb r0, [r0, #0x0] /*r0 has target bank*/
lsl r0, #0x1
ldr r1, .MovesUsed /*r1 has MovesUsed*/
add r0, r1 /*Target's moved used?*/
ldrh r6, [r0]
ldrh r0, [r0] /*r0 has the move that target is going to use*/
ldr r1, .MoveTable /*r1 now has MoveTable*/
mov r2, #0xc /*move data is C bytes*/
mul r0, r2 /*move ID x C*/
add r0, r1 /*get move offset*/
ldrb r0, [r0, #0xA]
ldrb r3, [r0, #0x0] /*r0 should now have move effect*/
cmp r0, #0x2
beq Abort
StealMove:
ldr r1, .EffectTable
mov r2, #0x4
mul r3, r2
add r1, r3 /*r1 should now be at the correct offset of the move table*/
ldr r1, [r1] /*r1 should now have the effect script offset*/
ldr r0, .CurrentScript
str r1, [r0]
b End
Abort:
ldr r0, .CurrentScript
ldr r1, .FailScript
str r1, [r0, #0x0]
b End
End:
pop {r0}
bx r0
.align 2
.UserBank: .word 0x02023D6B
.TargetBank: .word 0x02023D6C
.BattleStruct: .word 0x02023BE4
.BasePower: .word 0x02023F50
.TurnOrder: .word 0x02023bde
.MonsMoved: .word 0x02023be2
.MovesUsed: .word 0x02023dc4
.MoveTable: .word 0x08(offset of your move data table)
.EffectTable: .word 0x08(offset of your move effect table)
.CurrentScript: .word 0x02023d74
.FailScript: .word 0x081D7DF0
And finally, use this battle script:
Spoiler:
#org @MeFirst
attackcanceler
attackstring
callasm 0x8(offset of the first ASM routine + 1)
attackanimation
waitanimation
callasm 0x8(offset of the second ASM routine + 1)
setbyte 0x2023FDC 0x0
setbyte 0x2023FDD 0x0
printstring 0x4
callasm 0x8(offset of the third ASM routine + 1)
I know this method seems rather ridiculous to require 3 callasm's (and maybe there might be some redundant checks left in there because they were all modified heavily from Doesnt's Sucker Punch routine), but basically this method insures that it first prints "[user] used Me First!", does Me First's unique animation, then updates the RAM to the stolen Move ID, then says, "[user] used [stolen move]!" and plays the stolen move's animation. Having three check routines in between commands was necessary for Me First to have it's own unique animation AND still play the new animation afterwards AND display the updated string afterwards.
-----------------------------------------------------
(these particles are just for Power Trick and Wring Out. Use Psych Up's movement for Power Trick, and use Gust's movement for Wring Out)
(FireRed) Psycho Cut animation that looks more similar to the in-game one. Psycho Cut is not a contact move, so this would be more fitting (it's basically Air Cutter with the Psychic background). Basically the concept is that the user creates a blade with his/her Psychic powers.
Also have some particles. They're already indexed. Use the Aura Sphere particle with Shadow Ball's movement and that bright-blue BG. Use the Energy Ball particle with Shadow Ball's movement as well. Use the Power Gem particle with Hidden Power's movement. And lastly, the Sucker Punch particle can be used for any Dark or Poison move where you want a purple hit marker.