Registrarse

[Decomp-GBA] Error "relocation truncated to fit" al querer desarrollar un nuevo movimiento.

Estado
Cerrado para nuevas respuestas.

TheYellowRaptor

Usuario de oro
Buenas! Comencé a trabajar en un proyectito personal de decomp en pokeemerald y tratando de crear un nuevo ataque me salta el error del título y no sé que significa ni cómo resolverlo. Esto va a ser un poco largo, así que me disculpo por anticipado.

No soy programador ni tengo mucha experiencia en ello, pero algo logro entender empleando lo que ya existe. Me puse en campaña para crear un nuevo ataque (al que llamé "Hold Position") que maximice el stat DEF pero minice el stat ATK y, debido al enorme parecido que tiene con Tambor, decidí usarlo como base. Así que recreé todo exactamente igual que ese ataque: Definí el nuevo ataque en "moves.h" (ampliando la cantidad de "MOVES_COUNT"), añadí el ataque al archivo "battle_moves.h", le agregué una descripción en "move_descriptions.h" y un nombre en "move_names.h". Luego de eso creé un nuevo efecto (llamado como el movimiento: "EFFECT_HOLD_POSITION") e hice lo mismo: lo definí en "battle_moves_effects.h" y se lo asigné al movimiento.
Ahora empieza lo mas grueso del proceso: en el archivo en "battle_script_1.s" vi cómo funcionaba el ataque tambor, y vi que tenía la función (o comando, no estoy seguro de cómo llamarlo) "maxattackhalvehp". Fui al archivo "battle_script_commands.c" para ver cómo funcionaba y me encontré con lo siguiente:
Código:
static void Cmd_maxattackhalvehp(void) // belly drum
{
    u32 halfHp = gBattleMons[gBattlerAttacker].maxHP / 2;

    if (!(gBattleMons[gBattlerAttacker].maxHP / 2))
        halfHp = 1;

    if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] < MAX_STAT_STAGE
        && gBattleMons[gBattlerAttacker].hp > halfHp)
    {
        gBattleMons[gBattlerAttacker].statStages[STAT_ATK] = MAX_STAT_STAGE;
        gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 2;
        if (gBattleMoveDamage == 0)
            gBattleMoveDamage = 1;

        gBattlescriptCurrInstr += 5;
    }
    else
    {
        gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
    }
}
No termino de entender qué hace el "T1_READ_PTR(gBattlescriptCurrInstr+1)", pero como sólo sucede si no se cumple el segundo "if", decidí dejarlo tal como está. El resto del código es bastante sencillo de interpretar, así que lo copié debajo, le quité todo lo referente a reducir los HP y lo modifiqué lo suficiente como para que cumpla la función que deseo, dejándolo así:
Código:
static void Cmd_maxdefenseminattack(void) // Hold position
{
    if (gBattleMons[gBattlerAttacker].statStages[STAT_DEF] < MAX_STAT_STAGE)
    {
        gBattleMons[gBattlerAttacker].statStages[STAT_DEF] = MAX_STAT_STAGE;
        gBattleMons[gBattlerAttacker].statStages[STAT_ATK] = MIN_STAT_STAGE;

        gBattlescriptCurrInstr += 5;
    }
    else
    {
        gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
    }
}
Tranquilos, definí el "Cmd_maxdefenseminattack(void)" al inicio del archivo (en la parte del "static void") y como constante en "gBattleScriptingCommandsTable[]" (el valor que, creo yo, tiene asignado es el 0xFA, que es el siguiente después del útlimo).

Nuevamente fui a "battle_script_1.s" y agregué el efecto de la siguiente manera:
Código:
BattleScript_EffectHoldPosition::
    attackcanceler
    attackstring
    ppreduce
    maxdefenseminattack BattleScript_ButItFailed
    attackanimation
    waitanimation
    printstring STRINGID_HOLDPOSITION
    waitmessage B_WAIT_TIME_LONG
    goto BattleScript_MoveEnd
Lo último que hice fue agregar en "battle_script.inc" el .macro "maxdefenseminattack" (tal como el de belly drum), dejándolo tal que así:
Código:
    .macro maxdefenseminattack param0:req
    .byte 0xfa
    .byte \param0
    .endm
La cosa es que al compilar la ROM, me salta el error que ya les mencioné, de la siguiente manera (sin las comillas):
"data/battle_scripts_1.o: in function `BattleScript_EffectHoldPosition':
(script_data+0x155b): relocation truncated to fit: R_ARM_ABS8 against symbol `BattleScript_ButItFailed' defined in script_data section in data/battle_scripts_1.o"
Supongo que debe ser algo con a función "param0", que no tengo ni idea de qué es ni de para qué sirve; o puede que haya cometido un error en algún paso anterior. También se me ocurre que puede deberse a que el macro no se halla en 0xFA, sino que en otra parte.
Así que eso, cualquier ayuda que puedan brindarme será bien recibida. ¡Gracias!
 

Kaiser de Emperana

Called in hand
Me salteé el 90% de tu mensaje. Así que no tengo ni idea de que funcionalidad querés hacer. Mucho menos de si está bien programada.

Pero el error que te está marcando es en el macro. Vos estás declarando que "param0" se debe guardar en un byte. Pero en tu script le estás pasando un puntero a "BattleScript_ButItFailed". Los punteros ocupan 4 bytes. Por eso el compilador te está diciendo que truncó el valor a un byte, para poder guardarlo.

La solución sería cambiar tu macro para que quede:
Código:
    .macro maxdefenseminattack param0:req
    .byte 0xfa
    .4byte \param0
    .endm
 

TheYellowRaptor

Usuario de oro
Me salteé el 90% de tu mensaje. Así que no tengo ni idea de que funcionalidad querés hacer. Mucho menos de si está bien programada.

Pero el error que te está marcando es en el macro. Vos estás declarando que "param0" se debe guardar en un byte. Pero en tu script le estás pasando un puntero a "BattleScript_ButItFailed". Los punteros ocupan 4 bytes. Por eso el compilador te está diciendo que truncó el valor a un byte, para poder guardarlo.

La solución sería cambiar tu macro para que quede:
Código:
    .macro maxdefenseminattack param0:req
    .byte 0xfa
    .4byte \param0
    .endm
No puedo creer que un detalle así se me halla escapado. Ya compiló todo correctamente.
¡Muchísimas gracias por la ayuda!
 
Estado
Cerrado para nuevas respuestas.
Arriba