Assembly code questions

Hi, it’s me, again with more questions about the assembly code, I thanks in advance everyone who will read this post, because with my English it will not be easy :sweat_smile:

I have several questions, I start from the simplest to the most complex:

Unit's Magic with Str/Mag split

I’ve tried to create an ability that checks whether character X’s magic value differs from Y’s physical defense
and if the difference was positive for X, X got a bonus, I say in advance that I succeeded, and it seems to work but …

   .thumb
.equ SavageMagicID, SkillTester+4

.equ gBattleData, 0x203A4D4


push {r4-r7, lr}
mov r4, r0 @atkr
mov r5, r1 @dfdr

@has the skill
ldr r0, SkillTester
mov lr, r0
mov r0, r4 @attacker data
ldr r1, SavageMagicID
.short 0xf800
cmp r0, #0
beq End

@make sure we're in combat (or combat prep)
ldrb r3, =gBattleData
ldrb r3, [r3]
cmp r3, #4
beq End

mov r6, #0x3A @take magic of atk
ldrb r0, [r4, r6] @magic atk
ldrb r1, [r5, #0x17] @defender defense
cmp r0, r1
ble End @skip if str is less or equal

@add 2 damage
mov r1, #0x5a
ldrh r0, [r4, r1] @atk
add r0, #2
strh r0, [r4,r1]

@ add 10 crit
mov r0, r4
add     r0,#0x66    @Move to the attacker's crit.
ldrh    r3,[r0]     @Load the attacker's crit into r3.
add     r3,#10      @add 10.
strh    r3,[r0]     @Store.

End:
pop {r4-r7}
pop {r0}
bx r0
.align
.ltorg
SkillTester:
@Poin SkillTester
@WORD SavageMagicID

to make this code work I had to enter a string (the first of the second box)
I wanted to ask if it is correct to do so because not inserting it doesn’t work as if not going to take the value of the unit’s magic.

mov r6, #0x3A @take magic of atk
ldrb r0, [r4, r6] @magic atk
ldrb r1, [r5, #0x17] @defender defense
cmp r0, r1
ble End @skip if str is less or equal
Blow Skill

I tried to create a skill with the effect similar to hose “Blow”
My idea was that when X attacks Y, and if Y has less than 50% life total, X gets a bonus

> WindStrikeSkill:
> ldr r0, =0x203a56c @defender
> ldrb r1, [r0, #0x12] @maxhp
> lsr r1, #1 @max hp/2
> ldrb r0, [r0, #0x13] @currhp
> cmp r0, r1
> beq SkillReturn *line 189*
> ldr     r0,=0x203A4EC       @Move attacker data into r0.
> add     r0,#0x5a    @Move to the attacker's dmg.
> ldrh    r3,[r0]     @Load the attacker's dmg into r3.
> add     r3,#3    @Add 3 to the attacker's dmg.
> strh    r3,[r0]     @Store attacker dmg.
> add     r0,#0x60    @Move to the attacker's hit.
> ldrh    r3,[r0]     @Load the attacker's hit into r3.
> add     r3,#0x0F    @Add 15 to the attacker's hit.
> strh    r3,[r0]     @Store attacker hit.
> add     r0,#0x66    @Move to the attacker's crit.
> ldrh    r3,[r0]     @Load the attacker's hit into r3.
> add     r3,#0x0A    @Add 10 to the attacker's crit.
> strh    r3,[r0]     @Store attacker crit.
> add     r0,#0x5E    @Move to the attacker's AS.
> ldrh    r3,[r0]     @Load the attacker's AS into r3.
> add     r3,#0x02    @Add 2 to the attacker's AS.
> strh    r3,[r0]     @Store attacker AS.
> b       SkillReturn	@Attacker's attack. Redundancy? Nah.

I put this code in Check Blows because I believe it falls into that category … but my problem is that when I try to assemble all the code it brings me an error
4
in the code box I have indicated which line 189 is

my idea is that i got out of the control loop … i went to see and made this change

CheckLoop:
mov r0, r5
ldr     r2,BlowIDList   @Load in the list of Blow Skills.
ldrb    r1,[r2,r4]  @Load in the next Blow Skill in the list.
ldr     r3,SkillTester
mov     lr, r3     
.short 0xf800       @Call Skill Tester.
cmp r0, #0          @Check if unit has the corresponding Faire skill.
bne SkillChecks
SkillReturn:
add     r4, #0x01
cmp     r4, #0x0B *0x0A to 0x0B*
bne     CheckLoop
b       EndProgram
SkillChecks:
cmp     r4, #0x00
beq     DuelistsSkill
cmp     r4, #0x01
beq     DeathSkill
cmp     r4, #0x02
beq     DartingSkill
cmp     r4, #0x03
beq     WardingSkill
cmp     r4, #0x04
beq     CertainSkill
cmp     r4, #0x05
beq     ArmoredSkill
cmp     r4, #0x06
beq     QuickDrawSkill
cmp     r4, #0x07
beq     ChivalrySkill
cmp     r4, #0x08
beq     PragmaticSkill
cmp		r4, #0x09
beq		HeroesDeathSkill
cmp     r4, #0x0A *my*
beq     WindStrikeSkill *my*
b SkillReturn

in the same folder, in the EVENT file I also inserted “WindStrikeID” (my skill)

ALIGN 4
BlowCheck:
#incbin "BlowCheck.dmp"
POIN SkillTester
POIN BlowIDList

ALIGN 4
BlowIDList:
BYTE DuelistsBlowID DeathBlowID DartingBlowID WardingBlowID CertainBlowID ArmoredBlowIDQuickDrawID ChivalryID PragmaticID HeroesDeathBlowID WindStrikeID 

but it keeps giving me the same error and I don’t understand why

Mounted unit problems

I have tried to change the function of the calculation of mounted aid, my idea would simply be to allow a mounted unit to be able to assist any type of unit, except other other mounted units.
to solve my problem I decided to use Pikmin’s “preventRescue” code and to change the calculation of for mounted unit:
In the base game, through No$gba I made this little change:

ORG $18A12
SHORT 0x1840 // change to add 

instead of doing (20+[5])-Unit’s costitution) now it adds up and works in the Vanilla game, but obviously not in my buildfile, because I believe that the Skill System is going to change the position of the code so I started looking for the file that made this change, and I found this:
(the path that I have followed: Engine Hacks->Neessary->StatGetters->Aid.event)
to give it a try I made a change 19 to 40

#ifndef MODULAR_GETTER_AID_EVENT
#define MODULAR_GETTER_AID_EVENT

#include "_Common.event"

pAidModifiers: // Aid
	POIN prAddUnitFinalConstitution prSubstractOne prAdjustAidIfMounted
	#ifdef DEBUFFS_MIN_ZERO
	POIN prMinZero
	#endif
WORD 0

prAddUnitFinalConstitution:
	rAdd(rCallExternal(prConGetter))

prSubstractOne:
	rSubConst(1)

prAdjustAidIfMounted:
{
	rIfUnitHasAttribute(CA_MOUNTEDAID)
		rCallSequence(_prNegate _prAddBaseMountedAidBonus _prAddMoreIfNotFemale)

_prNegate:
	rMinus(rCurrent)

_prAddBaseMountedAidBonus:
	rAddConst(40) *my change*

_prAddMoreIfNotFemale: // Stupid mechanic imo, but we're going vanilla so :shrug:
	rIfUnitHasNotAttribute(CA_FEMALE, rAddConst(5))
}

#endif // MODULAR_GETTER_AID_EVENT

now I finally tested this gearbox, and it seems to solve my problem, but I’d rather add up, and not increase the value, but I can’t understand what should be changed, also because I’m afraid of breaking everything :sweat_smile:
i think the solution is same inside this file, but i can’t figure out how to do it

My second problem is that also for some strange reason I can’t get the Pikmin code related to the class IDs to work:

ALIGN 4
NewRescueTargetList:
#incbin "TryAddUnitToRescueTargetList.dmp"
POIN RescuerTable
POIN RescueeTable

PUSH
ORG $25344
GotoNewRescueFunc:
#incbin "GotoNewFunc.dmp"
POIN NewRescueTargetList + 1
POP

ALIGN 4
RescuerTable:
#incbin "BlankTable.dmp"

ALIGN 4
RescueeTable:
#incbin "BlankTable.dmp"

#define CannotRescue(unitid) "PUSH; ORG RescuerTable + unitid; BYTE 0x1; POP"
#define CannotBeRescued(unitid) "PUSH; ORG RescueeTable + unitid; BYTE 0x1; POP"

// Vanilla FE8 Phantoms
CannotRescue(0x3B)
CannotRescue(0x3E)
CannotRescue(0x3F)
CannotBeRescued(0x3B)
CannotBeRescued(0x3E)
CannotBeRescued(0x3F)
// my
CannotRescue(0x01)
CannotRescue(0x02)
CannotBeRescued(0x05)
CannotBeRescued(0x07)

CannotRescue commands seem to work for me but the commands CannotBeRescued they don’t work…or rather the strange thing, which only sees my first definition
`

CannotBeRescued(0x05)
and not the second, now my perplexity is that there is an ID limit that I can go to put
(0x05 is cavalier class and 0x07 is paladin class)
I think I have correctly made the changes indicated on the post of the relevant code on the class IDs
I don’t understand what he did wrong, because it doesn’t fit in my buildfile than in the Vanilla game someone who uses this code, can help me?
I already feel guilty for making a post on pikmin’s one to report a bug that was not related to its code, for this I prefer to ask it here, and I apologize to Pikmin

Shove like Tellius

Final question, I thought I’d recreate how the “shove” mechanic works like in Tellius’ games my idea was to insert a check in the shove skill code
the check I would like to do at the end would be similar to the one using a unit in the base game to see if it can rescue another unit
with the only change, to change the position of the “constitution” and “Aid”
ie if X has higher costitution than Y aid, then you can use shove in order to do this, I think I just need to find the CanRescue function of a Unit
but I will be dumbbut I would not know where to look, especially due to the fact of the various changes that I would like to make above :sweat_smile:
so i guess it’s better to get the above thing working first, and then do this?

Sorry for the stupid questions, but I need some help :sweat_smile:
and thank you very much again for all those who will waste time reading this post, thanks

Yeah this should be correct for getting a unit’s magic.

For your blow problem, firstly, see how you’re doing

ldr r0, =0x0203A4EC
add r0, r0, #0x5A
ldrh r3, [ r0 ]
add r3, r3, #3
strh r3, [ r0 ]
@ So far so good...
add r0, r0, #0x60 @ Here, you're not adding 0x60 to 0x0203A4EC, you're adding it to 0x0203A4EC+0x5A.
...

For your assembling error, you need to change around how you’re handling your branches. Branch commnads have a limited range, so you need to find a way to make sure all of your branches are in range. Unconditional b has a longer range than conditional b--, so if your error tells you it’s a conditional branch that’s the problem, instead of

blt SomeLabel

you can do

bge Skip
b SomeLabel
Skip:

If the error is on an unconditional branch, then you need to implement a ladder where you jump to another unconditional branch which can branch to your intended label.

I don’t really know anything about @Pikmin1211 's hack here, but it looks like you might be overcomplicating your issue. All you need to do is change wherever it checks to see whether one unit can rescue another (likely the rescue command’s usability and target list building routine, or maybe if you’re lucky, they share some sort of CanUnitRescue function).

Instead of having a CanRescue function share utility with shoving, it would probably be best to write the behavior you want without calling it.

2 Likes

Hi Snakey1, hanks again for helping me, it seems you have become my savior :smile:

Good, it seems that one thing I managed to do it correctly hahahaha

if I understood correctly, basically the bloop, the one that uses the “blow” skill code, it is limited (I believe in the value #0x0A)
but at the same time it is also the most “capacious” I wouldn’t want to shoot a bullshit, but wasn’t it the same one we used for my “ForLady” skill? and in theory that didn’t check for all unit IDs?

if i understand, the idea to solve my problem is to create a second loop right after the first one?
I didn’t quite understand the difference between an uncoditional and conditional branch
the error that the assembler reports to me doesn’t report me this information…
now i’m confused :sweat_smile:

most likely yes

yes I think it’s a good idea … I could create a check that checks if a unit uses the byte “mounted unit calculation” and hence say that it cannot be rescued
i think it’s worth trying to see if my idea works, my problem is i don’t understand where i have to go to look in the buildfile to make this change, because I still can’t find where to make the sum between the constitution and the aid bonus for the mounted units.

Yes you are right, it is better to create a separate code for the “shove” command, but I think it is worth finding the CanRescue function to see how it works, because in the end my code should imitate it anyway, except for a few steps
i think for me it can be a good starting point to create this code, I think
the problem arose mainly because I don’t understand where the SkillSystem goes to reposition these vanilla game codes

I’m not 100% sure what you’re trying to say here to be honest, but if I remember correctly, the blow skills check values in the blow skill list and branch accordingly. Your problem is that the branch that the assembler error directs you to is out of range, so you need to set up an additional branch in some way (following the directions from my previous post) such that no branches are out of range.

An unconditional branch always branches without condition. This is simply your b (Label) opcode. A conditional branch is a branch that checks the CPU status flags in deciding whether to branch or not. These would be your bge (Label), beq (Label), bne (Label), etc. You’d put a cmp ... in front of these most likely. I notated these with b--.

I don’t think I fully read into your rescuing problem from before, so sorry about that. This insight might be better:
Your change that you made was to the Modular Stat Getter formula for a unit’s aid. You added a large value to the unit’s aid if they are mounted, which should accomplish what you want, but it’s a hacky solution. It seems you want a more real solution, which is good.
You need to find where the game decides “Can this unit rescue this other unit?” How do you find where it does that? That’s a pretty common challenge with debugging/research, and there isn’t always a clear-cut solution. Taking what we know about how it decides this, we know that it checks for a unit’s constitution and a unit’s aid. We can utilize no$gba and break on read for a unit’s constitution and invoke the unit menu. Alternatively, we can put a break on the aid getter formula. Either of these should work. Once you find where this decision happens, you can modify the code as you please. You may need to edit code in multiple places to fully implement this change.

1 Like

Sorry for the late reply Snakey, and also for not being able to explain well, my fault that I mixed several problems in one cauldron, so in order not to get confused, it is better to proceed step by step.

I’m pretty sure this is the problem, because I tried putting my code in place of one of the “originals” of the file and it seemed to me that it worked (I only did the assembly)

it would be what I tried to write in the previous post, but because of the translator and my English I have created confusion in my old post, so now I try to “explain” what I wanted to do right through the code, or at least I try

CheckLoop:
mov r0, r5
ldr     r2,BlowIDList   @Load in the list of Blow Skills.
ldrb    r1,[r2,r4]  @Load in the next Blow Skill in the list.
ldr     r3,SkillTester
mov     lr, r3     
.short 0xf800       @Call Skill Tester.
cmp r0, #0          @Check if unit has the corresponding Faire skill.
bne SkillChecks
SkillReturn:
add     r4, #0x01
cmp     r4, #0x0A
bne     CheckLoop
b       EndProgram
SkillChecks:
cmp     r4, #0x00
beq     DuelistsSkill
cmp     r4, #0x01
beq     DeathSkill
cmp     r4, #0x02
beq     DartingSkill
cmp     r4, #0x03
beq     WardingSkill
cmp     r4, #0x04
beq     CertainSkill
cmp     r4, #0x05
beq     ArmoredSkill
cmp     r4, #0x06
beq     QuickDrawSkill
cmp     r4, #0x07
beq     ChivalrySkill
cmp     r4, #0x08
beq     PragmaticSkill
cmp		r4, #0x09
beq		HeroesDeathSkill
**cmp     r4, #0x0A *my***
**beq     WindStrikeSkill *my***
b SkillReturn

this is the original code of the blow skill loop, except the penultimate two strings.
now I try to show what I would like to try to do

CheckLoop:
mov r0, r5
ldr     r2,BlowIDList   @Load in the list of Blow Skills.
ldrb    r1,[r2,r4]  @Load in the next Blow Skill in the list.
ldr     r3,SkillTester
mov     lr, r3     
.short 0xf800       @Call Skill Tester.
cmp r0, #0          @Check if unit has the corresponding Faire skill.
bne SkillChecks
SkillReturn:
add     r4, #0x01
cmp     r4, #0x0A
bne     CheckLoop
b       EndProgram
SkillChecks:
cmp     r4, #0x00
beq     DuelistsSkill
cmp     r4, #0x01
beq     DeathSkill
cmp     r4, #0x02
beq     DartingSkill
cmp     r4, #0x03
beq     WardingSkill
cmp     r4, #0x04
beq     CertainSkill
cmp     r4, #0x05
beq     ArmoredSkill
cmp     r4, #0x06
beq     QuickDrawSkill
cmp     r4, #0x07
beq     ChivalrySkill
cmp     r4, #0x08
beq     PragmaticSkill
cmp		r4, #0x09
beq		pass 2 @ if it is none of the above then go to another loop
b SkillReturn
  
pass 2:
mov r4, #0 @ let's reset the loop counter to 0
SkillReturn 2:
add     r4, #0x01
cmp     r4, #0x0A
bne     CheckLoop
b       EndProgram
SkillChecks 2:
cmp     r4, #0x00
beq     HeroesDeathSkill
cmp     r4, #0x01
beq     WindStrikeSkill
b SkillReturn 2
EndProgram:		@I had to move this to stop out of range errors. - Darrman
pop {r4-r7}
pop {r0}
bx r0
@the various skills of the two loops and my skill
WindStrikeSkill:
ldr r0, =0x203a56c @defender
ldrb r1, [r0, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r0, #0x13] @currhp
cmp r0, r1
beq SkillReturn 2 @ now i hope this work
ldr     r0,=0x203A4EC       @Move attacker data into r0.
add     r0,#0x5a    @Move to the attacker's dmg.
ldrh    r3,[r0]     @Load the attacker's dmg into r3.
add     r3,#3    @Add 3 to the attacker's dmg.
strh    r3,[r0]     @Store attacker dmg.
add     r0,#0x60    @Move to the attacker's hit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#0x0F    @Add 15 to the attacker's hit.
strh    r3,[r0]     @Store attacker hit.
add     r0,#0x66    @Move to the attacker's crit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#0x0A    @Add 10 to the attacker's crit.
strh    r3,[r0]     @Store attacker crit.
add     r0,#0x5E    @Move to the attacker's AS.
ldrh    r3,[r0]     @Load the attacker's AS into r3.
add     r3,#0x02    @Add 2 to the attacker's AS.
strh    r3,[r0]     @Store attacker AS.
b       SkillReturn 2 	@Attacker's attack. Redundancy? Nah.

.align
.ltorg
SkillTester:
@POIN SkillTester
@POIN BlowIDList

now hopefully you understand what I did, I tried to create a new branch of the first loop by creating a second loop subordinate to the first, more or less this was my idea, I tell the truth, I have not really seen if it works, I wrote it just now in the forum post, as soon as I can see if it can be a solution, and with all sincerity, even if it worked, I don’t know if the best way to solve the problem, and I didn’t understand if this was more or less what you tried to say, really sorry, it’s not easy for me to “write” and “read” in English

thank you very much for the explanation, I feel like an idiot, a confusion was born in my mind more due to the fact that I didn’t understand the words in English, than the basic concept

instead about my other problem, although I’m not very good at using the debugger I managed, thro
ugh the information of the Tequila tutorial, although I am not very good at using the debugger, I managed, through the information of the Tequila tutorial, to reach the part of the code regarding the equation for calculating the mounted aid:



this is the small operation I did in the debugger, and it works! :grinning:

but only in the Vanilla game…and it doesn’t work with the Skill System now doing the Tequila tutorial search operation in a modified rom with skillsystem:


the modification is completely influential on the assembly game code modified by the SkillSystem

following step by step the guide arrived at this point:


as you can see from the second photo, the arrival point is completely different from that the vanilla game,
browsing the page a little, I recognize the names of some SkillSystem functions, such as take passive bonus from an item, in this case i thinh, the game think, that the unit recieve a bonus of its costitution, from this point, I start to get lost in a labyrinth that becomes more and more intricate for me, now as these functions are not present in the base game, somewhere in the SkillSystem buildfile, there must be a file that replaces the original function by moving it to another place
following my simple logic, I arrive at the statgetters folder, in the aid.event

#ifndef MODULAR_GETTER_AID_EVENT
#define MODULAR_GETTER_AID_EVENT

#include "_Common.event"

pAidModifiers: // Aid
	POIN prAddUnitFinalConstitution prSubstractOne prAdjustAidIfMounted
	#ifdef DEBUFFS_MIN_ZERO
	POIN prMinZero
	#endif
WORD 0

prAddUnitFinalConstitution:
	rAdd(rCallExternal(prConGetter))

prSubstractOne:
	rSubConst(1)

prAdjustAidIfMounted:
{
	rIfUnitHasAttribute(CA_MOUNTEDAID)
		rCallSequence(_prNegate _prAddBaseMountedAidBonus _prAddMoreIfNotFemale)

_prNegate:
	rMinus(rCurrent) 

_prAddBaseMountedAidBonus:
	rAddConst(19)

_prAddMoreIfNotFemale: // Stupid mechanic imo, but we're going vanilla so :shrug:
	rIfUnitHasNotAttribute(CA_FEMALE, rAddConst(5))
}

#endif // MODULAR_GETTER_AID_EVENT

now I wonder, to achieve my purpose, do I have to go change something in here?

_prNegate:
	rMinus(rCurrent) 

I don’t know, I don’t think this is the way to go, but that’s what I found on my own following my simple dumb logic… to move on to my other problems, i think it is best to solve this first of all, I hope I have explained myself a little better, and i know i may sound a little silly, but really thanks for the help you try to give me, really thanks!

(Minus the asterisks) this looks good… except that your branch is out of range. I’ll fix that in a second.

You probably want to set this to terminate at 0x0B.

So if the line beq WindStrikeSkill is out of range, I would instead do something like

cmp r4, #0x09
beq HeroesDeathSkill
cmp r4, #0x0A
bne NotWindStrike
b WindStrikeSkill
NotWindStrike:
b SkillReturn

Generally speaking, you shouldn’t have spaces in your labels, by the way.
Then, I would do

WindStrikeSkill: @ Recall that we checked the skill of the unit in r4. We now want to check the HP of the other unit who may not necessarily be the defender!
ldrb r1, [r5, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r5, #0x13] @currhp
cmp r0, r1
beq SkillReturn
mov   r1,#0x5A    @Move to the damage.
ldrh    r3,[r4,r1]     @Load the damage.
add    r3,#3    @Add 3 to the damage.
strh    r3,[r4,r1]     @Store damage.
mov   r1, #0x5A    @Move to the hit.
ldrh    r3,[r4,r1]     @Load the hit
add    r3,#15    @Add 15 to the hit.
strh    r3,[r4,r1]     @Store hit.
mov    r1,#0x66    @Move to the crit.
ldrh     r3,[r4,r1]     @Load the crit.
add     r3,#10    @Add 10 to the crit.
strh     r3,[r4,r1]     @Store crit.
mov    r1,#0x5E    @Move to the AS.
ldrh     r3,[r4,r1]     @Load the AS into r3.
add     r3,#2    @Add 2 to the AS.
strh     r3,[r4,r1]     @Store AS.
b       SkillReturn

I mentioned before that you were incorrectly moving to the various battle stats. Instead of adding to the battle struct pointer, I’d just move the offsets into another register and load from two registers like this. You can do it by adding to the battle struct pointer; it’s just a matter of preference.

Now my code here will work (assuming it works) for either a defender or an attacker. If you want this to only apply to an attacker, you need to add a check to see if r4 is 0x0203A4EC. If not, jump to SkillReturn.

For the rescue hack now, you’ve found the modular stat getters. It’s a system that allows for designing “routines” with only event assembler. There’s going to be one function that’s the “aid getter.” If you can find that function (which it looks like you have), you can go to it’s parent function- i.e. whatever called it. From there, instead of having it check the aid and constitution of units, you can implement your own behavior. I don’t think you need to make any edits to the aid getter at all. I just suggested it as a way to find what you do want to edit.

1 Like

so I rewrote the loop like this:

> CheckLoop:
> mov r0, r5
> ldr     r2,BlowIDList   @Load in the list of Blow Skills.
> ldrb    r1,[r2,r4]  @Load in the next Blow Skill in the list.
> ldr     r3,SkillTester
> mov     lr, r3     
> .short 0xf800       @Call Skill Tester.
> cmp r0, #0          @Check if unit has the corresponding Faire skill.
> bne SkillChecks
> SkillReturn:
> add     r4, #0x01
> cmp     r4, #0x0B
> bne     CheckLoop
> b       EndProgram
> SkillChecks:
> cmp     r4, #0x00
> beq     DuelistsSkill
> cmp     r4, #0x01
> beq     DeathSkill
> cmp     r4, #0x02
> beq     DartingSkill
> cmp     r4, #0x03
> beq     WardingSkill
> cmp     r4, #0x04
> beq     CertainSkill
> cmp     r4, #0x05
> beq     ArmoredSkill
> cmp     r4, #0x06
> beq     QuickDrawSkill
> cmp     r4, #0x07
> beq     ChivalrySkill
> cmp     r4, #0x08
> beq     PragmaticSkill
> cmp		r4, #0x09
> beq		HeroesDeathSkill
> cmp     r4, #0x0A
> bne NotWindStrike
> b WindStrikeSkill
> NotWindStrike:
> b SkillReturn

but unfortunately he always keeps telling me that I’m out of the branch

while for the other problem

you must excuse me, but I don’t understand very well,

you refer to the one I found in the debugger, or to the .event file that I found in the Skill System, I believe the second?

if so, I should look for a relative function? right? I looked in the folder but I didn’t find anything else or at least for my completely inexperienced eyes
pg7
I tried to see also in the subfolder “_asm”

and the only thing I found interesting was this code snippet

.thumb
.align

.global prGetItemConBonus
.type prGetItemConBonus, %function

.equ STAT_CON, 0x7
.macro blh to, reg=r3
	ldr \reg, =\to
	mov lr, \reg
	.short 0xF800
.endm
.equ GetUnitEquippedItem,0x8016B28

prGetItemConBonus:
push {r4-r7,r14}
mov r4,r1 @unit
mov r5,r0 @stat

ldr r3,=GetUnitEquippedItem
mov r14,r3
mov r0,r4
.short 0xF800

mov r1,r0
cmp r1,#0
beq RetFalse
mov r0,#0xFF
and r0,r1
lsl r1,r0,#3
add r1,r1,r0
lsl r1,r1,#2
ldr r0,=ItemTable
add r1,r1,r0
ldr r0,[r1,#0xC]
cmp r0,#0
bne RetStat

RetFalse:
mov r0,#0
b GoBack

RetStat:
ldrb r0,[r0,#0x7]
add r5,r0

GoBack:
mov r1,r4
mov r0,r5

pop {r4-r7}
pop {r1}
bx r1

.ltorg
.align

is from the file “GetItemConBonus.s” and it exactly matches the code I found in the debugger

and seeing it from here, it seems to confirm my idea that it serves to see if the unit has anything that increases the relative constitution of the unit

I’m really sorry not to be able to fully understand

That’s okay. Language barrier is rough :confused:

For which line is it giving you the error exactly? For whatever line you have the error, you need to change how you branch to prevent that kind of error.

For the rescuing problem, let me back up a little bit.
What you’re trying to do is change how the game decides whether someone can rescue someone else, right? Well, we need to find where it makes this determination. We need to figure out how to find this spot in the code. This is a common problem for designing hacks, and it can be one of the most difficult problems to overcome.
A good starting place is thinking about what the vanilla behavior of the code is. We know that it takes a unit’s constitution and a unit’s aid into account when determining this. Right off the bat we have two pathways to find this determination! I suggested that we break on the aid getter to help find this spot in the code because to check aid, it must call the aid getter. Once we’ve halted execution on the aid getter, we can look at the value of r14, link register. This is has an address within the parent function, the function that called the aid getter. Most likely, this parent function is what you want to edit. (Alternatively, we can see if a function exists that has a name that seems to be what we want, like CanRescue would be sensible. Personally I would try searching a library of function offsets first, but it’s a good exercise to find a calculation like this.)
I’m not saying you need to make any edits to the aid getter to accomplish what you want. I’m saying you can use it to find the code that you do want to edit, the code that says “can this unit rescue this other unit or not?”.

1 Like

the line that takes me out of the branch is always the same:

WindStrikeSkill: @ Recall that we checked the skill of the unit in r4. We now want to check the HP of the other unit who may not necessarily be the defender!
ldrb r1, [r5, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r5, #0x13] @currhp
cmp r0, r1
beq SkillReturn @ this evil line!!!
mov   r1,#0x5A    @Move to the damage.
ldrh    r3,[r4,r1]     @Load the damage.
add    r3,#3    @Add 3 to the damage.
strh    r3,[r4,r1]     @Store damage.
mov   r1, #0x5A    @Move to the hit.
ldrh    r3,[r4,r1]     @Load the hit
add    r3,#15    @Add 15 to the hit.
strh    r3,[r4,r1]     @Store hit.
mov    r1,#0x66    @Move to the crit.
ldrh     r3,[r4,r1]     @Load the crit.
add     r3,#10    @Add 10 to the crit.
strh     r3,[r4,r1]     @Store crit.
mov    r1,#0x5E    @Move to the AS.
ldrh     r3,[r4,r1]     @Load the AS into r3.
add     r3,#2    @Add 2 to the AS.
strh     r3,[r4,r1]     @Store AS.
b       SkillReturn

is always the “beq SkillReturn” command inside my skill that create problem

ok, now I think I understand better, from the debugger I have to put a break to the function that allows to rescue an unit, right? is there a document that can help me find the point where a unit can help?

Oh wait, re-reading your message I have to find the function that sees when a unit can rescue, inserting a break in the aid getter? quite right?
and if I understood correctly, I have to put a break to the function when it does the calculation of the aid of a unit? in my case, the one for mounted units…right?
Now, I have found through FEbuilderGBA something that maybe can help us:


Could this be the routine we seek?

I don’t know whether to reassure me with this sentence or to scare me hahahaha

Ah I see. In that case, you need to follow the kind of format I had before to fix the conditional branch out of range with something like

cmp r0, r1
bne ApplyWindStrike @ Writing this, it occurs to me this only applies if current HP is exactly half of max HP. Are you sure this is the behavior you want?
b SkillReturn @ This works because b has a MUCH larger range than any conditional branch.
ApplyWindStrike:
mov r1, #0x5A

For rescue, you’re almost there. This is the function that tells the “Rescue” option in the unit menu whether it should display or not, and it considers all adjacent units. I think the subroutine, MakeRescueTargetList would have the part that determines whether this individual unit can rescue this other individual unit.
Good job on finding another way to what you want to find! Oftentimes there are many ways to get where you want to go with research, and you’ve found one of the better paths.

1 Like

I entered the code, and it finally assembled! :smile:
but when I went to test it, unfortunately my skill doesn’t work properly:


to test it, I put the ability on Eirika, the first thing I wanted to see was if the control worked correctly, that is, if the target of the attack, the defender, had less than 50% of his HP, the thing that immediately struck me as strange, is its exaggerated damage rate, (for a test I put the bonus on the attack very high, so you could easily see if the ability worked), but it seems that the check fails, that is, it does not really check if the target has less than 50% HP, also, the strangest thing is that it doesn’t charge the other bonuses, on the AS and the HIT, not sure, but sure it doesn’t charge bonus on critical hit, because it should have at least +10 critical.

WindStrikeSkill:
ldr r0, =0x203a56c @defender
ldrb r1, [r0, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r0, #0x13] @currhp
cmp r0, r1
bne ApplyWindStrike
b SkillReturn @ This works because b has a MUCH larger range than any conditional branch.
ApplyWindStrike:
mov r1, #0x5A
ldr     r0,=0x203A4EC       @Move attacker data into r0.
add     r0,#0x5a    @Move to the attacker's dmg.
ldrh    r3,[r0]     @Load the attacker's dmg into r3.
add     r3,#20    @Add 3 to the attacker's dmg.
strh    r3,[r0]     @Store attacker dmg.
add     r0,#0x60    @Move to the attacker's hit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#0x0F    @Add 15 to the attacker's hit.
strh    r3,[r0]     @Store attacker hit.
add     r0,#0x66    @Move to the attacker's crit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#0x0A    @Add 10 to the attacker's crit.
strh    r3,[r0]     @Store attacker crit.
add     r0,#0x5E    @Move to the attacker's AS.
ldrh    r3,[r0]     @Load the attacker's AS into r3.
add     r3,#0x02    @Add 2 to the attacker's AS.
strh    r3,[r0]     @Store attacker AS.
b       SkillReturn	@Attacker's attack. Redundancy? Nah.

now the enabling code would look like this, what did I do wrong?

I also noticed another problem, I don’t know if you remember my old skill “ForLady” which was going to check byte number 40 of an unit…now it seems to give me a problem, honestly i don’t know if she gave it to me before and i didn’t notice it, or something else I’ll put the code in for a moment, because I was sure it worked:

.equ AuraSkillCheck, SkillTester+4
.equ ForLadyID, AuraSkillCheck+4
.thumb
push {r4-r7,lr}
@goes in the battle loop.
@r0 is the attacker
@r1 is the defender
mov r4, r0
mov r5, r1

@has ForLady
ldr r1, SkillTester
mov lr, r1
mov r1, r5 @Attacker data
ldr r0, ForLadyID
.short 0xf800
cmp r1, #0 
beq Done

CheckSkill:
@now check for the skill
ldr r0, AuraSkillCheck
mov lr, r0
mov r0, r4 @attacker
ldr r1, ForLadyID
mov r1, #0x0
mov r2, #0 @can_trade
mov r3, #2 @range
.short 0xf800
cmp r0, #0
beq Done

CheckGender:
mov r3,#0x48
ldr r5,CharData
sub r2,#0x1
mul r3,r2
add r5,r3
ldr r0, [r5] @char
ldr r0, [r0, #0x28] @char abilities
ldr r1, [r5,#4] @class
ldr r1, [r1,#0x28] @class abilities
orr r0, r1
mov r1, #0x40
lsl r1, #8 @0x4000 IsFemale
tst r0, r1
bne Final

Final:
mov r0, r4
add     r0,#0x5A    @Move to the attacker's damage.
ldrh    r3,[r0]     @Load the attacker's damage into r3.
add     r3,#2    @add 2 damage.
strh    r3,[r0]     @Store dmg.

add     r0,#0x6    @Move to the attacker's hit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#10    @add 10 hit.
strh    r3,[r0]     @Store.

Done:
pop {r4-r7}
pop {r0}
bx r0
.align
.ltorg
CharData:
.long 0x202be4c
MovementPoin:
.long 0x880bb96
SkillTester:
@POIN SkillTester
@ POIN AuraSkillCheck
@ WORD ForLadyID

The problem is actually very simple I think, which charges the attack bonus both to the attacker and to the female character (defender), but I want you to load it only at the first one, I don’t understand how this is possible

mov r0, r4
add     r0,#0x5A    @Move to the attacker's damage.
ldrh    r3,[r0]     @Load the attacker's damage into r3.
add     r3,#2    @add 2 damage.
strh    r3,[r0]     @Store dmg.

add     r0,#0x6    @Move to the attacker's hit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#10    @add 10 hit.
strh    r3,[r0]     @Store.

shouldn’t he only charge the attacker buff? Am I not going to touch the defender’s logs here? tell me I did something wrong

returning to the rescue problem, if I understand correctly, then that snippet of code I found through FEbuilderGBA is fine, and it helps us to solve my problem, now my idea, very stupid, would be to simply check if the unit you are trying to rescue has the byte “mounted unit calculation aid” right? in theory I already have a code that goes to do this, but for another byte, that of ForLady, my ability!

mov r3,#0x48
ldr r5,CharData
sub r2,#0x1
mul r3,r2
add r5,r3
ldr r0, [r5] @char
ldr r0, [r0, #0x28] @char abilities
ldr r1, [r5,#4] @class
ldr r1, [r1,#0x28] @class abilities
orr r0, r1
mov r1, #0x40
lsl r1, #8 @0x4000 IsFemale
tst r0, r1
bne Final

only my problem is that this checks the “ability 2”, because the byte I’m going to look for lies in the “ability 1”!

I also had another idea, one could go and see if the unit being rescued has the ability “canto”, in my project the mounted units are the only ones to have canto and canto plus!
can it be another idea?

The pre battle calc loop works like this:

calculate attacker’s stats -> check skills with attacker as r0, defender as r1
-> calculate defender’s stats -> check skills with attacker as r1, defender as r0

So if you want to do anything that involves the other unit’s stats, you have to do it in the
check skills with attacker as r1, defender as r0 step.

Hence you will need something like this:

mov r4, r0
ldr r0,=0x203a4ec @attacker
cmp r4,r0
beq End

However this way your code only runs once by the calc loop, so you may want to run your code twice, once with r4 as the attacker, once with r5 as the attacker.

2 Likes

Hi
thank you for the help and explanation about the pre battle calc loop
but forgive my inexperience, I didn’t understand what you mean, are you talking about the “blow” skill or my other skill (ForLady)?

re-reading the message, I think I understand that this code must go to verify my other skill “ForLady”
because i want only the attacker get the bonus, right?
I apologize for not being good, this together with my lack of knowledge of English, it makes me confused

EDIT: maybe I was able to solve the strange problem with the code of my old skill:

.equ AuraSkillCheck, SkillTester+4
.equ ForLadyID, AuraSkillCheck+4
.thumb
push {r4-r7,lr}
@goes in the battle loop.
@r0 is the attacker
@r1 is the defender
mov r4, r0
mov r5, r1

@has ForLady
ldr r0, SkillTester
mov lr, r0
mov r0, r4 @Attacker data
ldr r1, ForLadyID
.short 0xf800
cmp r0, #0 
beq Done

CheckSkill:
@now check for the skill
ldr r0, AuraSkillCheck
mov lr, r0
mov r0, r4 @attacker
ldr r1, ForLadyID
mov r1, #0x0
mov r2, #0 @can_trade
mov r3, #2 @range
.short 0xf800
cmp r0, #0
beq Done

CheckGender:
mov r3,#0x48
ldr r5,CharData
sub r2,#0x1
mul r3,r2
add r5,r3
ldr r0, [r5] @char
ldr r0, [r0, #0x28] @char abilities
ldr r1, [r5,#4] @class
ldr r1, [r1,#0x28] @class abilities
orr r0, r1
mov r1, #0x40
lsl r1, #8 @0x4000 IsFemale
tst r0, r1
bne Final

Final:
mov r0, r4
add     r0,#0x5A    @Move to the attacker's damage.
ldrh    r3,[r0]     @Load the attacker's damage into r3.
add     r3,#2    @add 2 damage.
strh    r3,[r0]     @Store dmg.

add     r0,#0x6    @Move to the attacker's hit.
ldrh    r3,[r0]     @Load the attacker's hit into r3.
add     r3,#10    @add 10 hit.
strh    r3,[r0]     @Store.

Done:
pop {r4-r7}
pop {r0}
bx r0
.align
.ltorg
CharData:
.long 0x202be4c
MovementPoin:
.long 0x880bb96
SkillTester:
@POIN SkillTester
@ POIN AuraSkillCheck
@ WORD ForLadyID

this is the correct code, now below I put, the wrong part of code:

@has ForLady
ldr r1, SkillTester
mov lr, r1
mov r1, r5 @Attacker data
ldr r0, ForLadyID
.short 0xf800
cmp r1, #0 
beq Done

the difference is that in the old one, in this section I had confused the registers of the attacker and the defender, with the new code (the first new from EDIT) it seems to work as I would like
I’d love to hear from someone more experienced than me if my correction makes sense

@MintX you have to forgive me, but I have not yet understood, your code to whom you wanted to refer
thank you in advance for the help you are trying to give me, I really appreciate it very much :grinning:

I mentioned a potential mistake in your new blow skill earlier, but it’s okay if you didn’t notice it.

bne ApplyWindStrike
b SkillReturn @ This works because b has a MUCH larger range than any conditional branch.
ApplyWindStrike:

Think about what this is doing. This just compared current HP to half of max HP. Do you want to apply your skill if these are not exactly equal? That’s what it’s doing now. Change the bne to something more appropriate to match your intended behavior.

Likewise, you didn’t apply the changes I suggested with the code after ApplyWindStrike:. Try implementing that and see what happens.

What MintX suggested is an additional check to make sure that the bonus only applies to the initiator of the battle. I think you want this on both of your skills?

1 Like

You have to forgive me, but I feel like an idiot, I just can’t understand where is the mistake, now I re-publish the entire code

this is what is at the beginning of the code, which is the loop:

.thumb
.equ BlowIDList, SkillTester+4
push {r4-r7, lr}
mov     r4,#0 @loop counter
ldr     r5,=0x203a4ec @attacker
cmp     r0,r5
bne     EndProgram @skip if unit isn't the attacker
mov     r6,r1 
ldr     r1, [r6,#4] @class number
cmp     r1, #0
beq     EndProgram
CheckLoop:
mov r0, r5
ldr     r2,BlowIDList   @Load in the list of Blow Skills.
ldrb    r1,[r2,r4]  @Load in the next Blow Skill in the list.
ldr     r3,SkillTester
mov     lr, r3     
.short 0xf800       @Call Skill Tester.
cmp r0, #0          @Check if unit has the corresponding Faire skill.
bne SkillChecks
SkillReturn:
add     r4, #0x01
cmp     r4, #0x0B
bne     CheckLoop
b       EndProgram
SkillChecks:
cmp     r4, #0x00
beq     DuelistsSkill
cmp     r4, #0x01
beq     DeathSkill
cmp     r4, #0x02
beq     DartingSkill
cmp     r4, #0x03
beq     WardingSkill
cmp     r4, #0x04
beq     CertainSkill
cmp     r4, #0x05
beq     ArmoredSkill
cmp     r4, #0x06
beq     QuickDrawSkill
cmp     r4, #0x07
beq     ChivalrySkill
cmp     r4, #0x08
beq     PragmaticSkill
cmp		r4, #0x09
beq		HeroesDeathSkill
cmp     r4, #0x0A
bne NotWindStrike
b WindStrikeSkill
NotWindStrike:
b SkillReturn

EndProgram:		@I had to move this to stop out of range errors. - Darrman
pop {r4-r7}
pop {r0}
bx r0

This is the actual Skill’s code

WindStrikeSkill:
ldrb r1, [r5, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r5, #0x13] @currhp
cmp r0, r1
bne ApplyWindStrike
b SkillReturn @ This works because b has a MUCH larger range than any conditional branch.
ApplyWindStrike:	
mov   r1, #0x5A    @Move to the damage.
ldrh    r3, [r4,r1]     @Load the damage.
add    r3, #3    @Add 3 to the damage.
strh    r3, [r4,r1]     @Store damage.
mov   r1, #0x5A    @Move to the hit.
ldrh    r3, [r4,r1]     @Load the hit
add    r3, #15    @Add 15 to the hit.
strh    r3, [r4,r1]     @Store hit.
mov    r1, #0x66    @Move to the crit.
ldrh     r3, [r4,r1]     @Load the crit.
add     r3, #50    @Add 10 to the crit.
strh     r3, [r4,r1]     @Store crit.
mov    r1, #0x5E    @Move to the AS.
ldrh     r3, [r4,r1]     @Load the AS into r3.
add     r3, #2    @Add 2 to the AS.
strh     r3, [r4,r1]     @Store AS.
b       SkillReturn

.align
.ltorg
SkillTester:
@POIN SkillTester
@POIN BlowIDList

are these the changes i had to make? because I have tried and tried but it seems that the attack bonus is never loaded

yes exactly, I want them not to be the same, I want the current ones to be lower than the half of the total, so bne is correct in my case, I think

yes, I just want the attacker to take the bonus, in both of my skill, but second case, i think i have solved the problem, because only the owner of the skill ForLady take the bonus, now.

For checking HP, you’re using r5. Do you want to be using r4 instead?

1 Like

I’ve tried using r4, but it always doesn’t work, but I think it is more correct to use r5, because the information of the defender is stored there, or am I wrong? maybe I should create a new file, which makes me unlinked from blow skills

Oh duh my bad. I thought r4 was a battle unit pointer. It’s really a counter. In the code I suggested you use to affect the stats, use r5 instead of r4.

1 Like

Oh thank you very much indeed ,it’s not your fault, don’t worry, I also had to pay more attention to which registers I use, in fact in the code I published, I also found another error!
this is the correct code that seems to finally work! :grin:

WindStrikeSkill:
ldr r0, =0x203a56c @defender
ldrb r1, [r0, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r0, #0x13] @currhp
cmp r0, r1
blt ApplyWindStrike
b SkillReturn @ This works because b has a MUCH larger range than any conditional branch.
ApplyWindStrike:
ldr     r0,=0x203A4EC       @Move attacker data into r0.
mov   r1, #0x5A    @Move to the damage.
ldrh    r3, [r5,r1]     @Load the damage.
add    r3, #3    @Add 3 to the damage.
strh    r3, [r5,r1]     @Store damage.
mov   r1, #0x5A    @Move to the hit.
ldrh    r3, [r5,r1]     @Load the hit
add    r3, #15    @Add 15 to the hit.
strh    r3, [r5,r1]     @Store hit.
mov    r1, #0x66    @Move to the crit.
ldrh     r3, [r5,r1]     @Load the crit.
add     r3, #50    @Add 10 to the crit.
strh     r3, [r5,r1]     @Store crit.
mov    r1, #0x5E    @Move to the AS.
ldrh     r3, [r5,r1]     @Load the AS into r3.
add     r3, #2    @Add 2 to the AS.
strh     r3, [r5,r1]     @Store AS.
b       SkillReturn

.align
.ltorg
SkillTester:
@POIN SkillTester
@POIN BlowIDList

the error I found was at the very beginning of the check, that the code did not have the character specified to whom to check the logs, which I have corrected this way, and it now seems to work

ldr r0, =0x203a56c @defender
ldrb r1, [r0, #0x12] @maxhp
lsr r1, #1 @max hp/2
ldrb r0, [r0, #0x13] @currhp

thank you so much again for your help @Snakey1

now I have to see how to solve my other problem, but I think I can check the byte of a unit, like I did with my old skill…or how in theory the base game should , for the function of the sum of the bonus aid of a mounted unit

EDIT: I managed to navigate the debugger a bit, and I found the exact point where the game decides if a character is eligible to be rescued, or at least I think, the point is 80253B4.

my doubt is that, I don’t want to modify the base function, but add a new check, which coexists with the vanilla one

I don’t want to tell you how to do your job, but it seems 0x801831C is the actual ‘canRescue’ function. It simply compares the aid of the rescuer (obtained from 0x80189B8) and returns true if it’s bigger than the target’s con. You can change this to your desired rescuing conditions.

1 Like