Merge branch 'master' into unk_text_util_2

This commit is contained in:
PikalaxALT
2017-10-02 22:09:29 -04:00
committed by GitHub
351 changed files with 35376 additions and 45563 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,601 +0,0 @@
#include "global.h"
#include "battle.h"
#include "battle_move_effects.h"
#include "moves.h"
#include "abilities.h"
#include "item.h"
#include "items.h"
#include "hold_effects.h"
void atk00_attackcanceler(void);
void atk01_accuracycheck(void);
void atk02_attackstring(void);
void atk03_ppreduce(void);
void atk04_critcalc(void);
void atk05_damagecalc1(void);
void atk06_typecalc(void);
void atk07_dmg_adjustment(void);
void atk08_dmg_adjustment2(void);
void atk09_attackanimation(void);
void atk0A_waitanimation(void);
void atk0B_healthbarupdate(void);
void atk0C_datahpupdate(void);
void atk0D_critmessage(void);
void atk0E_effectiveness_sound(void);
void atk0F_resultmessage(void);
void atk10_printstring(void);
void atk11_printstring_playeronly(void);
void atk12_waitmessage(void);
void atk13_printfromtable(void);
void atk14_printfromtable_playeronly(void);
void atk15_seteffectwithchancetarget(void);
void atk16_seteffectprimary(void);
void atk17_seteffectsecondary(void);
void atk18_status_effect_clear(void);
void atk19_faint_pokemon(void);
void atk1A_faint_animation(void);
void atk1B_faint_effects_clear(void);
void atk1C_jumpifstatus(void);
void atk1D_jumpifstatus2(void);
void atk1E_jumpifability(void);
void atk1F_jumpifsideaffecting(void);
void atk20_jumpifstat(void);
void atk21_jumpifstatus3(void);
void atk22_jumpiftype(void);
void atk23_getexp(void);
void atk24(void);
void atk25_move_values_cleanup(void);
void atk26_set_multihit(void);
void atk27_decrement_multihit(void);
void atk28_goto(void);
void atk29_jumpifbyte(void);
void atk2A_jumpifhalfword(void);
void atk2B_jumpifword(void);
void atk2C_jumpifarrayequal(void);
void atk2D_jumpifarraynotequal(void);
void atk2E_setbyte(void);
void atk2F_addbyte(void);
void atk30_subbyte(void);
void atk31_copyarray(void);
void atk32_copyarray_withindex(void);
void atk33_orbyte(void);
void atk34_orhalfword(void);
void atk35_orword(void);
void atk36_bicbyte(void);
void atk37_bichalfword(void);
void atk38_bicword(void);
void atk39_pause(void);
void atk3A_waitstate(void);
void atk3B_healthbar_update(void);
void atk3C_return(void);
void atk3D_end(void);
void atk3E_end2(void);
void atk3F_end3(void);
void atk40_jump_if_move_affected_by_protect(void);
void atk41_call(void);
void atk42_jumpiftype2(void);
void atk43_jumpifabilitypresent(void);
void atk44(void);
void atk45_playanimation(void);
void atk46_playanimation2(void);
void atk47_setgraphicalstatchangevalues(void);
void atk48_playstatchangeanimation(void);
void atk49_moveendturn(void);
void atk4A_typecalc2(void);
void atk4B_return_atk_to_ball(void);
void atk4C_copy_poke_data(void);
void atk4D_switch_data_update(void);
void atk4E_switchin_anim(void);
void atk4F_jump_if_cannot_switch(void);
void atk50_openpartyscreen(void);
void atk51_switch_handle_order(void);
void atk52_switch_in_effects(void);
void atk53_trainer_slide(void);
void atk54_effectiveness_sound(void);
void atk55_play_sound(void);
void atk56_fainting_cry(void);
void atk57(void);
void atk58_return_to_ball(void);
void atk59_learnmove_inbattle(void);
void atk5A(void);
void atk5B_80256E0(void);
void atk5C_hitanimation(void);
void atk5D_getmoneyreward(void);
void atk5E_8025A70(void);
void atk5F_8025B24(void);
void atk60_increment_gamestat(void);
void atk61_8025BA4(void);
void atk62_08025C6C(void);
void atk63_jumptorandomattack(void);
void atk64_statusanimation(void);
void atk65_status2animation(void);
void atk66_chosenstatusanimation(void);
void atk67_8025ECC(void);
void atk68_80246A0(void);
void atk69_dmg_adjustment2(void);
void atk6A_removeitem(void);
void atk6B_atknameinbuff1(void);
void atk6C_lvlbox_display(void);
void atk6D_set_sentpokes_values(void);
void atk6E_set_atk_to_player0(void);
void atk6F_set_visible(void);
void atk70_record_ability(void);
void atk71_buffer_move_to_learn(void);
void atk72_jump_if_can_run_frombattle(void);
void atk73_hp_thresholds(void);
void atk74_hp_thresholds2(void);
void atk75_8026A58(void);
void atk76_various(void);
void atk77_setprotect(void);
void atk78_faintifabilitynotdamp(void);
void atk79_setatkhptozero(void);
void atk7A_jumpwhiletargetvalid(void);
void atk7B_healhalfHP_if_possible(void);
void atk7C_8025508(void);
void atk7D_set_rain(void);
void atk7E_setreflect(void);
void atk7F_setseeded(void);
void atk80_manipulatedamage(void);
void atk81_setrest(void);
void atk82_jumpifnotfirstturn(void);
void atk83_nop(void);
void atk84_jump_if_cant_sleep(void);
void atk85_stockpile(void);
void atk86_stockpiletobasedamage(void);
void atk87_stockpiletohpheal(void);
void atk88_negativedamage(void);
void atk89_statbuffchange(void);
void atk8A_normalisebuffs(void);
void atk8B_setbide(void);
void atk8C_confuseifrepeatingattackends(void);
void atk8D_setmultihit_counter(void);
void atk8E_prepare_multihit(void);
void atk8F_forcerandomswitch(void);
void atk90_conversion_type_change(void);
void atk91_givepaydaymoney(void);
void atk92_setlightscreen(void);
void atk93_ko_move(void);
void atk94_gethalfcurrentenemyhp(void);
void atk95_setsandstorm(void);
void atk96_weatherdamage(void);
void atk97_try_infatuation(void);
void atk98_status_icon_update(void);
void atk99_setmist(void);
void atk9A_set_focusenergy(void);
void atk9B_transformdataexecution(void);
void atk9C_set_substitute(void);
void atk9D_copyattack(void);
void atk9E_metronome(void);
void atk9F_dmgtolevel(void);
void atkA0_psywavedamageeffect(void);
void atkA1_counterdamagecalculator(void);
void atkA2_mirrorcoatdamagecalculator(void);
void atkA3_disablelastusedattack(void);
void atkA4_setencore(void);
void atkA5_painsplitdmgcalc(void);
void atkA6_settypetorandomresistance(void);
void atkA7_setalwayshitflag(void);
void atkA8_copymovepermanently(void);
void atkA9_sleeptalk_choose_move(void);
void atkAA_set_destinybond(void);
void atkAB_DestinyBondFlagUpdate(void);
void atkAC_remaininghptopower(void);
void atkAD_spite_ppreduce(void);
void atkAE_heal_party_status(void);
void atkAF_cursetarget(void);
void atkB0_set_spikes(void);
void atkB1_set_foresight(void);
void atkB2_setperishsong(void);
void atkB3_rolloutdamagecalculation(void);
void atkB4_jumpifconfusedandstatmaxed(void);
void atkB5_furycuttercalc(void);
void atkB6_happinesstodamagecalculation(void);
void atkB7_presentdamagecalculation(void);
void atkB8_set_safeguard(void);
void atkB9_magnitudedamagecalculation(void);
void atkBA_jumpifnopursuitswitchdmg(void);
void atkBB_setsunny(void);
void atkBC_maxattackhalvehp(void);
void atkBD_copyfoestats(void);
void atkBE_breakfree(void);
void atkBF_set_defense_curl(void);
void atkC0_recoverbasedonsunlight(void);
void atkC1_hidden_power(void);
void atkC2_selectnexttarget(void);
void atkC3_setfutureattack(void);
void atkC4_beat_up(void);
void atkC5_hidepreattack(void);
void atkC6_unhidepostattack(void);
void atkC7_setminimize(void);
void atkC8_sethail(void);
void atkC9_jumpifattackandspecialattackcannotfall(void);
void atkCA_setforcedtarget(void);
void atkCB_setcharge(void);
void atkCC_callterrainattack(void);
void atkCD_cureifburnedparalysedorpoisoned(void);
void atkCE_settorment(void);
void atkCF_jumpifnodamage(void);
void atkD0_settaunt(void);
void atkD1_set_helpinghand(void);
void atkD2_swap_items(void);
void atkD3_copy_ability(void);
void atkD4_wish_effect(void);
void atkD5_setroots(void);
void atkD6_doubledamagedealtifdamaged(void);
void atkD7_setyawn(void);
void atkD8_setdamagetohealthdifference(void);
void atkD9_scaledamagebyhealthratio(void);
void atkDA_abilityswap(void);
void atkDB_imprisoneffect(void);
void atkDC_setgrudge(void);
void atkDD_weightdamagecalculation(void);
void atkDE_asistattackselect(void);
void atkDF_setmagiccoat(void);
void atkE0_setstealstatchange(void);
void atkE1_intimidate_string_loader(void);
void atkE2_switchout_abilities(void);
void atkE3_jumpiffainted(void);
void atkE4_getsecretpowereffect(void);
void atkE5_pickup(void);
void atkE6_castform_change_animation(void);
void atkE7_castform_data_change(void);
void atkE8_settypebasedhalvers(void);
void atkE9_setweatherballtype(void);
void atkEA_recycleitem(void);
void atkEB_settypetoterrain(void);
void atkEC_pursuit_sth(void);
void atkED_802B4B4(void);
void atkEE_removelightscreenreflect(void);
void atkEF_pokeball_catch_calculation(void);
void atkF0_copy_caught_poke(void);
void atkF1_setpoke_as_caught(void);
void atkF2_display_dex_info(void);
void atkF3_nickname_caught_poke(void);
void atkF4_802BEF0(void);
void atkF5_removeattackerstatus1(void);
void atkF6_802BF48(void);
void atkF7_802BF54(void);
void sub_8056EF8(void);
void (* const gBattleScriptingCommandsTable[])(void) =
{
atk00_attackcanceler,
atk01_accuracycheck,
atk02_attackstring,
atk03_ppreduce,
atk04_critcalc,
atk05_damagecalc1,
atk06_typecalc,
atk07_dmg_adjustment,
atk08_dmg_adjustment2,
atk09_attackanimation,
atk0A_waitanimation,
atk0B_healthbarupdate,
atk0C_datahpupdate,
atk0D_critmessage,
atk0E_effectiveness_sound,
atk0F_resultmessage,
atk10_printstring,
atk11_printstring_playeronly,
atk12_waitmessage,
atk13_printfromtable,
atk14_printfromtable_playeronly,
atk15_seteffectwithchancetarget,
atk16_seteffectprimary,
atk17_seteffectsecondary,
atk18_status_effect_clear,
atk19_faint_pokemon,
atk1A_faint_animation,
atk1B_faint_effects_clear,
atk1C_jumpifstatus,
atk1D_jumpifstatus2,
atk1E_jumpifability,
atk1F_jumpifsideaffecting,
atk20_jumpifstat,
atk21_jumpifstatus3,
atk22_jumpiftype,
atk23_getexp,
atk24,
atk25_move_values_cleanup,
atk26_set_multihit,
atk27_decrement_multihit,
atk28_goto,
atk29_jumpifbyte,
atk2A_jumpifhalfword,
atk2B_jumpifword,
atk2C_jumpifarrayequal,
atk2D_jumpifarraynotequal,
atk2E_setbyte,
atk2F_addbyte,
atk30_subbyte,
atk31_copyarray,
atk32_copyarray_withindex,
atk33_orbyte,
atk34_orhalfword,
atk35_orword,
atk36_bicbyte,
atk37_bichalfword,
atk38_bicword,
atk39_pause,
atk3A_waitstate,
atk3B_healthbar_update,
atk3C_return,
atk3D_end,
atk3E_end2,
atk3F_end3,
atk40_jump_if_move_affected_by_protect,
atk41_call,
atk42_jumpiftype2,
atk43_jumpifabilitypresent,
atk44,
atk45_playanimation,
atk46_playanimation2,
atk47_setgraphicalstatchangevalues,
atk48_playstatchangeanimation,
atk49_moveendturn,
atk4A_typecalc2,
atk4B_return_atk_to_ball,
atk4C_copy_poke_data,
atk4D_switch_data_update,
atk4E_switchin_anim,
atk4F_jump_if_cannot_switch,
atk50_openpartyscreen,
atk51_switch_handle_order,
atk52_switch_in_effects,
atk53_trainer_slide,
atk54_effectiveness_sound,
atk55_play_sound,
atk56_fainting_cry,
atk57,
atk58_return_to_ball,
atk59_learnmove_inbattle,
atk5A,
atk5B_80256E0,
atk5C_hitanimation,
atk5D_getmoneyreward,
atk5E_8025A70,
atk5F_8025B24,
atk60_increment_gamestat,
atk61_8025BA4,
atk62_08025C6C,
atk63_jumptorandomattack,
atk64_statusanimation,
atk65_status2animation,
atk66_chosenstatusanimation,
atk67_8025ECC,
atk68_80246A0,
atk69_dmg_adjustment2,
atk6A_removeitem,
atk6B_atknameinbuff1,
atk6C_lvlbox_display,
atk6D_set_sentpokes_values,
atk6E_set_atk_to_player0,
atk6F_set_visible,
atk70_record_ability,
atk71_buffer_move_to_learn,
atk72_jump_if_can_run_frombattle,
atk73_hp_thresholds,
atk74_hp_thresholds2,
atk75_8026A58,
atk76_various,
atk77_setprotect,
atk78_faintifabilitynotdamp,
atk79_setatkhptozero,
atk7A_jumpwhiletargetvalid,
atk7B_healhalfHP_if_possible,
atk7C_8025508,
atk7D_set_rain,
atk7E_setreflect,
atk7F_setseeded,
atk80_manipulatedamage,
atk81_setrest,
atk82_jumpifnotfirstturn,
atk83_nop,
atk84_jump_if_cant_sleep,
atk85_stockpile,
atk86_stockpiletobasedamage,
atk87_stockpiletohpheal,
atk88_negativedamage,
atk89_statbuffchange,
atk8A_normalisebuffs,
atk8B_setbide,
atk8C_confuseifrepeatingattackends,
atk8D_setmultihit_counter,
atk8E_prepare_multihit,
atk8F_forcerandomswitch,
atk90_conversion_type_change,
atk91_givepaydaymoney,
atk92_setlightscreen,
atk93_ko_move,
atk94_gethalfcurrentenemyhp,
atk95_setsandstorm,
atk96_weatherdamage,
atk97_try_infatuation,
atk98_status_icon_update,
atk99_setmist,
atk9A_set_focusenergy,
atk9B_transformdataexecution,
atk9C_set_substitute,
atk9D_copyattack,
atk9E_metronome,
atk9F_dmgtolevel,
atkA0_psywavedamageeffect,
atkA1_counterdamagecalculator,
atkA2_mirrorcoatdamagecalculator,
atkA3_disablelastusedattack,
atkA4_setencore,
atkA5_painsplitdmgcalc,
atkA6_settypetorandomresistance,
atkA7_setalwayshitflag,
atkA8_copymovepermanently,
atkA9_sleeptalk_choose_move,
atkAA_set_destinybond,
atkAB_DestinyBondFlagUpdate,
atkAC_remaininghptopower,
atkAD_spite_ppreduce,
atkAE_heal_party_status,
atkAF_cursetarget,
atkB0_set_spikes,
atkB1_set_foresight,
atkB2_setperishsong,
atkB3_rolloutdamagecalculation,
atkB4_jumpifconfusedandstatmaxed,
atkB5_furycuttercalc,
atkB6_happinesstodamagecalculation,
atkB7_presentdamagecalculation,
atkB8_set_safeguard,
atkB9_magnitudedamagecalculation,
atkBA_jumpifnopursuitswitchdmg,
atkBB_setsunny,
atkBC_maxattackhalvehp,
atkBD_copyfoestats,
atkBE_breakfree,
atkBF_set_defense_curl,
atkC0_recoverbasedonsunlight,
atkC1_hidden_power,
atkC2_selectnexttarget,
atkC3_setfutureattack,
atkC4_beat_up,
atkC5_hidepreattack,
atkC6_unhidepostattack,
atkC7_setminimize,
atkC8_sethail,
atkC9_jumpifattackandspecialattackcannotfall,
atkCA_setforcedtarget,
atkCB_setcharge,
atkCC_callterrainattack,
atkCD_cureifburnedparalysedorpoisoned,
atkCE_settorment,
atkCF_jumpifnodamage,
atkD0_settaunt,
atkD1_set_helpinghand,
atkD2_swap_items,
atkD3_copy_ability,
atkD4_wish_effect,
atkD5_setroots,
atkD6_doubledamagedealtifdamaged,
atkD7_setyawn,
atkD8_setdamagetohealthdifference,
atkD9_scaledamagebyhealthratio,
atkDA_abilityswap,
atkDB_imprisoneffect,
atkDC_setgrudge,
atkDD_weightdamagecalculation,
atkDE_asistattackselect,
atkDF_setmagiccoat,
atkE0_setstealstatchange,
atkE1_intimidate_string_loader,
atkE2_switchout_abilities,
atkE3_jumpiffainted,
atkE4_getsecretpowereffect,
atkE5_pickup,
atkE6_castform_change_animation,
atkE7_castform_data_change,
atkE8_settypebasedhalvers,
atkE9_setweatherballtype,
atkEA_recycleitem,
atkEB_settypetoterrain,
atkEC_pursuit_sth,
atkED_802B4B4,
atkEE_removelightscreenreflect,
atkEF_pokeball_catch_calculation,
atkF0_copy_caught_poke,
atkF1_setpoke_as_caught,
atkF2_display_dex_info,
atkF3_nickname_caught_poke,
atkF4_802BEF0,
atkF5_removeattackerstatus1,
atkF6_802BF48,
atkF7_802BF54,
sub_8056EF8
};
struct statFractions
{
u8 dividend;
u8 divisor;
};
const struct statFractions gAccuracyStageRatios[] =
{
{ 33, 100}, // -6
{ 36, 100}, // -5
{ 43, 100}, // -4
{ 50, 100}, // -3
{ 60, 100}, // -2
{ 75, 100}, // -1
{ 1, 1}, // 0
{133, 100}, // +1
{166, 100}, // +2
{ 2, 1}, // +3
{233, 100}, // +4
{133, 50}, // +5
{ 3, 1}, // +6
};
// The chance is 1/N for each stage.
const u16 gCriticalHitChance[] = {16, 8, 4, 3, 2};
const u32 gStatusFlagsForMoveEffects[] =
{
0x00000000,
0x00000007,
0x00000008,
0x00000010,
0x00000020,
0x00000040,
0x00000080,
0x00000007,
0x00000008,
0x00000000,
0x00000070,
0x00000000,
0x00001000,
0x0000E000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00400000,
0x00000000,
0x00000000,
0x04000000,
0x08000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000C00,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000
};

View File

@@ -1,5 +1,5 @@
#include "global.h"
#include "battle_ai.h"
#include "battle_ai_script_commands.h"
#include "pokemon.h"
#include "battle.h"
#include "species.h"
@@ -73,10 +73,7 @@ extern const struct BaseStats gBaseStats[];
extern const u32 gBitTable[];
extern u8 * const gBattleAI_ScriptsTable[];
extern u8 GetBankIdentity(u8);
extern u8 b_first_side(u8, u8, u8);
extern u8 GetBankByPlayerAI(u8);
extern void TypeCalc(u16 move, u8 bankAtk, u8 bankDef);
extern void AI_CalcDmg(u8, u8);
extern u8 CheckMoveLimitations();
@@ -1805,7 +1802,7 @@ static void BattleAICmd_count_alive_pokemon(void)
u32 status;
bankOnField1 = gBattlePartyID[index];
status = GetBankIdentity(index) ^ 2;
bankOnField2 = gBattlePartyID[GetBankByPlayerAI(status)];
bankOnField2 = gBattlePartyID[GetBankByIdentity(status)];
}
else // in singles there's only one bank by side
{

11415
src/battle_script_commands.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,6 @@ extern bool8 sub_8092E9C(u8, u8, u8);
extern u16 gScriptItemId;
extern const u8 BerryTreeScript[];
extern const struct BerryTree gBlankBerryTree;
#define BERRY_NAME_LENGTH 6
@@ -804,6 +803,54 @@ const struct Berry gBerries[] =
},
};
const struct UnkStruct_0858AB24 gUnknown_0858AB24[] = {
{ 50, 20},
{ 50, 20},
{ 50, 20},
{ 50, 20},
{ 50, 20},
{ 50, 30},
{ 50, 30},
{ 50, 30},
{ 50, 30},
{ 50, 30},
{ 60, 50},
{ 60, 50},
{ 60, 50},
{ 60, 50},
{ 60, 50},
{ 80, 70},
{ 80, 70},
{ 80, 70},
{ 80, 70},
{ 80, 70},
{100, 100},
{100, 100},
{100, 100},
{100, 100},
{100, 100},
{130, 150},
{130, 150},
{130, 150},
{130, 150},
{130, 150},
{160, 250},
{160, 250},
{160, 250},
{160, 250},
{160, 250},
{180, 500},
{180, 500},
{180, 500},
{180, 500},
{180, 500},
{200, 750},
{200, 750},
{150, 200}
};
const struct BerryTree gBlankBerryTree = {};
// unused
void ClearEnigmaBerries(void)
{

View File

@@ -129,8 +129,7 @@ static const u8 *const gUnknown_08618178[][3] = {
},
};
extern const u8 gUnknown_089A6550[0xC0];
extern const u8 gMultiBootProgram_BerryGlitchFix_Start[0x3b34];
extern const u8 gMultiBootProgram_BerryGlitchFix_Start[0x3BF4];
extern const u8 gMultiBootProgram_BerryGlitchFix_End[];
// .text
@@ -174,7 +173,7 @@ static void berry_fix_main(void)
case 3:
if (berry_fix_text_update(1) == 1)
{
berry_fix_mb_manager->mb.masterp = gUnknown_089A6550;
berry_fix_mb_manager->mb.masterp = gMultiBootProgram_BerryGlitchFix_Start;
berry_fix_mb_manager->mb.server_type = 0;
MultiBootInit(&berry_fix_mb_manager->mb);
berry_fix_mb_manager->unk2 = 0;
@@ -189,7 +188,7 @@ static void berry_fix_main(void)
}
else if (++ berry_fix_mb_manager->unk2 > 180)
{
MultiBootStartMaster(&berry_fix_mb_manager->mb, gMultiBootProgram_BerryGlitchFix_Start, (u32)(gMultiBootProgram_BerryGlitchFix_End - gMultiBootProgram_BerryGlitchFix_Start), 4, 1);
MultiBootStartMaster(&berry_fix_mb_manager->mb, gMultiBootProgram_BerryGlitchFix_Start + ROM_HEADER_SIZE, (u32)(gMultiBootProgram_BerryGlitchFix_End - (gMultiBootProgram_BerryGlitchFix_Start + ROM_HEADER_SIZE)), 4, 1);
berry_fix_mb_manager->state = 5;
}
break;

314
src/bg.c
View File

@@ -1,21 +1,12 @@
#include "global.h"
#include "dma3.h"
#include "bg.h"
#include "dma3.h"
#include "gpu_regs.h"
#define DISPCNT_ALL_BG_AND_MODE_BITS 0x0F07
#define DISPCNT_ALL_BG_AND_MODE_BITS (DISPCNT_BG_ALL_ON | 0x7)
enum {
BG_CTRL_ATTR_VISIBLE = 1,
BG_CTRL_ATTR_CHARBASEINDEX = 2,
BG_CTRL_ATTR_MAPBASEINDEX = 3,
BG_CTRL_ATTR_SCREENSIZE = 4,
BG_CTRL_ATTR_PALETTEMODE = 5,
BG_CTRL_ATTR_PRIORITY = 6,
BG_CTRL_ATTR_MOSAIC = 7,
BG_CTRL_ATTR_WRAPAROUND = 8,
};
struct BgControl {
struct BgControl
{
struct BgConfig {
u16 visible:1;
u16 unknown_1:1;
@@ -35,7 +26,8 @@ struct BgControl {
u16 bgVisibilityAndMode;
};
struct BgConfig2 {
struct BgConfig2
{
u32 baseTile:10;
u32 basePalette:4;
u32 unk_3:18;
@@ -45,54 +37,36 @@ struct BgConfig2 {
u32 bg_y;
};
static struct BgControl gGpuBgConfigs;
static struct BgConfig2 gGpuBgConfigs2[4];
static u32 gDmaBusyBitfield[4];
static IWRAM_DATA struct BgControl sGpuBgConfigs;
static IWRAM_DATA struct BgConfig2 sGpuBgConfigs2[4];
static IWRAM_DATA u32 sDmaBusyBitfield[4];
u32 gUnneededFireRedVariable;
static const struct BgConfig gZeroedBgControlStruct = { 0 };
extern void SetGpuReg(u8 regOffset, u16 value);
extern void SetGpuReg_ForcedBlank(u8 regOffset, u16 value);
extern u16 GetGpuReg(u8 regOffset);
extern int CheckForSpaceForDma3Request(s16 index);
bool32 IsInvalidBg32(u8);
void ResetBgControlStructs();
u16 GetBgMetricTextMode(u8, u8);
u32 GetBgMetricAffineMode(u8, u8);
u32 GetBgType(u8);
void SetTextModeAndHideBgs();
bool8 IsInvalidBg(u8);
bool32 IsTileMapOutsideWram(u8);
void CopyRectToBgTilemapBufferRect(u8, void*, u8, u8, u8, u8, u8, u8, u8, u8, u8, u16, u16);
void CopyTileMapEntry(u16*, u16*, s32, u32, u32);
u32 GetTileMapIndexFromCoords(s32, s32, s32, u32, u32);
void WriteSequenceToBgTilemapBuffer(u8, u16, u8, u8, u8, u8, u8, s16);
static const struct BgConfig sZeroedBgControlStruct = { 0 };
void ResetBgs(void)
{
ResetBgControlStructs();
gGpuBgConfigs.bgVisibilityAndMode = 0;
sGpuBgConfigs.bgVisibilityAndMode = 0;
SetTextModeAndHideBgs();
}
void SetBgModeInternal(u8 bgMode)
static void SetBgModeInternal(u8 bgMode)
{
gGpuBgConfigs.bgVisibilityAndMode &= 0xFFF8;
gGpuBgConfigs.bgVisibilityAndMode |= bgMode;
sGpuBgConfigs.bgVisibilityAndMode &= 0xFFF8;
sGpuBgConfigs.bgVisibilityAndMode |= bgMode;
}
u8 GetBgMode(void)
{
return gGpuBgConfigs.bgVisibilityAndMode & 0x7;
return sGpuBgConfigs.bgVisibilityAndMode & 0x7;
}
void ResetBgControlStructs(void)
{
struct BgConfig* bgConfigs = &gGpuBgConfigs.configs[0];
struct BgConfig zeroedConfig = gZeroedBgControlStruct;
struct BgConfig* bgConfigs = &sGpuBgConfigs.configs[0];
struct BgConfig zeroedConfig = sZeroedBgControlStruct;
int i;
for (i = 0; i < 4; i++)
@@ -105,7 +79,7 @@ void Unused_ResetBgControlStruct(u8 bg)
{
if (IsInvalidBg(bg) == FALSE)
{
gGpuBgConfigs.configs[bg] = gZeroedBgControlStruct;
sGpuBgConfigs.configs[bg] = sZeroedBgControlStruct;
}
}
@@ -115,88 +89,88 @@ void SetBgControlAttributes(u8 bg, u8 charBaseIndex, u8 mapBaseIndex, u8 screenS
{
if (charBaseIndex != 0xFF)
{
gGpuBgConfigs.configs[bg].charBaseIndex = charBaseIndex & 0x3;
sGpuBgConfigs.configs[bg].charBaseIndex = charBaseIndex & 0x3;
}
if (mapBaseIndex != 0xFF)
{
gGpuBgConfigs.configs[bg].mapBaseIndex = mapBaseIndex & 0x1F;
sGpuBgConfigs.configs[bg].mapBaseIndex = mapBaseIndex & 0x1F;
}
if (screenSize != 0xFF)
{
gGpuBgConfigs.configs[bg].screenSize = screenSize & 0x3;
sGpuBgConfigs.configs[bg].screenSize = screenSize & 0x3;
}
if (paletteMode != 0xFF)
{
gGpuBgConfigs.configs[bg].paletteMode = paletteMode;
sGpuBgConfigs.configs[bg].paletteMode = paletteMode;
}
if (priority != 0xFF)
{
gGpuBgConfigs.configs[bg].priority = priority & 0x3;
sGpuBgConfigs.configs[bg].priority = priority & 0x3;
}
if (mosaic != 0xFF)
{
gGpuBgConfigs.configs[bg].mosaic = mosaic & 0x1;
sGpuBgConfigs.configs[bg].mosaic = mosaic & 0x1;
}
if (wraparound != 0xFF)
{
gGpuBgConfigs.configs[bg].wraparound = wraparound;
sGpuBgConfigs.configs[bg].wraparound = wraparound;
}
gGpuBgConfigs.configs[bg].unknown_2 = 0;
gGpuBgConfigs.configs[bg].unknown_3 = 0;
sGpuBgConfigs.configs[bg].unknown_2 = 0;
sGpuBgConfigs.configs[bg].unknown_3 = 0;
gGpuBgConfigs.configs[bg].visible = 1;
sGpuBgConfigs.configs[bg].visible = 1;
}
}
u16 GetBgControlAttribute(u8 bg, u8 attributeId)
{
if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
switch (attributeId)
{
case BG_CTRL_ATTR_VISIBLE:
return gGpuBgConfigs.configs[bg].visible;
return sGpuBgConfigs.configs[bg].visible;
case BG_CTRL_ATTR_CHARBASEINDEX:
return gGpuBgConfigs.configs[bg].charBaseIndex;
return sGpuBgConfigs.configs[bg].charBaseIndex;
case BG_CTRL_ATTR_MAPBASEINDEX:
return gGpuBgConfigs.configs[bg].mapBaseIndex;
return sGpuBgConfigs.configs[bg].mapBaseIndex;
case BG_CTRL_ATTR_SCREENSIZE:
return gGpuBgConfigs.configs[bg].screenSize;
return sGpuBgConfigs.configs[bg].screenSize;
case BG_CTRL_ATTR_PALETTEMODE:
return gGpuBgConfigs.configs[bg].paletteMode;
return sGpuBgConfigs.configs[bg].paletteMode;
case BG_CTRL_ATTR_PRIORITY:
return gGpuBgConfigs.configs[bg].priority;
return sGpuBgConfigs.configs[bg].priority;
case BG_CTRL_ATTR_MOSAIC:
return gGpuBgConfigs.configs[bg].mosaic;
return sGpuBgConfigs.configs[bg].mosaic;
case BG_CTRL_ATTR_WRAPAROUND:
return gGpuBgConfigs.configs[bg].wraparound;
return sGpuBgConfigs.configs[bg].wraparound;
}
}
return 0xFF;
}
u8 LoadBgVram(u8 bg, void *src, u16 size, u16 destOffset, u8 mode)
u8 LoadBgVram(u8 bg, const void *src, u16 size, u16 destOffset, u8 mode)
{
u16 offset;
s8 cursor;
if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
switch (mode)
{
case 0x1:
offset = gGpuBgConfigs.configs[bg].charBaseIndex * BG_CHAR_SIZE;
offset = sGpuBgConfigs.configs[bg].charBaseIndex * BG_CHAR_SIZE;
break;
case 0x2:
offset = gGpuBgConfigs.configs[bg].mapBaseIndex * BG_SCREEN_SIZE;
offset = sGpuBgConfigs.configs[bg].mapBaseIndex * BG_SCREEN_SIZE;
break;
default:
cursor = -1;
@@ -221,51 +195,51 @@ end:
return cursor;
}
void ShowBgInternal(u8 bg)
static void ShowBgInternal(u8 bg)
{
u16 value;
if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
value = gGpuBgConfigs.configs[bg].priority |
(gGpuBgConfigs.configs[bg].charBaseIndex << 2) |
(gGpuBgConfigs.configs[bg].mosaic << 6) |
(gGpuBgConfigs.configs[bg].paletteMode << 7) |
(gGpuBgConfigs.configs[bg].mapBaseIndex << 8) |
(gGpuBgConfigs.configs[bg].wraparound << 13) |
(gGpuBgConfigs.configs[bg].screenSize << 14);
value = sGpuBgConfigs.configs[bg].priority |
(sGpuBgConfigs.configs[bg].charBaseIndex << 2) |
(sGpuBgConfigs.configs[bg].mosaic << 6) |
(sGpuBgConfigs.configs[bg].paletteMode << 7) |
(sGpuBgConfigs.configs[bg].mapBaseIndex << 8) |
(sGpuBgConfigs.configs[bg].wraparound << 13) |
(sGpuBgConfigs.configs[bg].screenSize << 14);
SetGpuReg((bg << 1) + 0x8, value);
gGpuBgConfigs.bgVisibilityAndMode |= 1 << (bg + 8);
gGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
sGpuBgConfigs.bgVisibilityAndMode |= 1 << (bg + 8);
sGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
}
}
void HideBgInternal(u8 bg)
static void HideBgInternal(u8 bg)
{
if (IsInvalidBg(bg) == FALSE)
{
gGpuBgConfigs.bgVisibilityAndMode &= ~(1 << (bg + 8));
gGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
sGpuBgConfigs.bgVisibilityAndMode &= ~(1 << (bg + 8));
sGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
}
}
void SyncBgVisibilityAndMode()
static void SyncBgVisibilityAndMode(void)
{
SetGpuReg(0, (GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS) | gGpuBgConfigs.bgVisibilityAndMode);
SetGpuReg(0, (GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS) | sGpuBgConfigs.bgVisibilityAndMode);
}
void SetTextModeAndHideBgs()
void SetTextModeAndHideBgs(void)
{
SetGpuReg(0, GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS);
}
void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
static void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
{
struct BgAffineSrcData src;
struct BgAffineDstData dest;
switch (gGpuBgConfigs.bgVisibilityAndMode & 0x7)
switch (sGpuBgConfigs.bgVisibilityAndMode & 0x7)
{
case 1:
if (bg != 2)
@@ -320,7 +294,7 @@ void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable)
for (i = 0; i < 4; i++)
{
gDmaBusyBitfield[i] = 0;
sDmaBusyBitfield[i] = 0;
}
gUnneededFireRedVariable = leftoverFireRedLeafGreenVariable;
@@ -347,13 +321,13 @@ void InitBgsFromTemplates(u8 bgMode, const struct BgTemplate *templates, u8 numT
0,
0);
gGpuBgConfigs2[bg].baseTile = templates[i].baseTile;
gGpuBgConfigs2[bg].basePalette = 0;
gGpuBgConfigs2[bg].unk_3 = 0;
sGpuBgConfigs2[bg].baseTile = templates[i].baseTile;
sGpuBgConfigs2[bg].basePalette = 0;
sGpuBgConfigs2[bg].unk_3 = 0;
gGpuBgConfigs2[bg].tilemap = NULL;
gGpuBgConfigs2[bg].bg_x = 0;
gGpuBgConfigs2[bg].bg_y = 0;
sGpuBgConfigs2[bg].tilemap = NULL;
sGpuBgConfigs2[bg].bg_x = 0;
sGpuBgConfigs2[bg].bg_y = 0;
}
}
}
@@ -373,13 +347,13 @@ void InitBgFromTemplate(const struct BgTemplate *template)
0,
0);
gGpuBgConfigs2[bg].baseTile = template->baseTile;
gGpuBgConfigs2[bg].basePalette = 0;
gGpuBgConfigs2[bg].unk_3 = 0;
sGpuBgConfigs2[bg].baseTile = template->baseTile;
sGpuBgConfigs2[bg].basePalette = 0;
sGpuBgConfigs2[bg].unk_3 = 0;
gGpuBgConfigs2[bg].tilemap = NULL;
gGpuBgConfigs2[bg].bg_x = 0;
gGpuBgConfigs2[bg].bg_y = 0;
sGpuBgConfigs2[bg].tilemap = NULL;
sGpuBgConfigs2[bg].bg_x = 0;
sGpuBgConfigs2[bg].bg_y = 0;
}
}
@@ -388,18 +362,18 @@ void SetBgMode(u8 bgMode)
SetBgModeInternal(bgMode);
}
u16 LoadBgTiles(u8 bg, void* src, u16 size, u16 destOffset)
u16 LoadBgTiles(u8 bg, const void* src, u16 size, u16 destOffset)
{
u16 tileOffset;
u8 cursor;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_PALETTEMODE) == 0)
{
tileOffset = (gGpuBgConfigs2[bg].baseTile + destOffset) * 0x20;
tileOffset = (sGpuBgConfigs2[bg].baseTile + destOffset) * 0x20;
}
else
{
tileOffset = (gGpuBgConfigs2[bg].baseTile + destOffset) * 0x40;
tileOffset = (sGpuBgConfigs2[bg].baseTile + destOffset) * 0x40;
}
cursor = LoadBgVram(bg, src, size, tileOffset, DISPCNT_MODE_1);
@@ -409,7 +383,7 @@ u16 LoadBgTiles(u8 bg, void* src, u16 size, u16 destOffset)
return -1;
}
gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
if (gUnneededFireRedVariable == 1)
{
@@ -419,7 +393,7 @@ u16 LoadBgTiles(u8 bg, void* src, u16 size, u16 destOffset)
return cursor;
}
u16 LoadBgTilemap(u8 bg, void *src, u16 size, u16 destOffset)
u16 LoadBgTilemap(u8 bg, const void *src, u16 size, u16 destOffset)
{
u8 cursor;
@@ -430,19 +404,19 @@ u16 LoadBgTilemap(u8 bg, void *src, u16 size, u16 destOffset)
return -1;
}
gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
return cursor;
}
u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset)
u16 Unused_LoadBgPalette(u8 bg, const void *src, u16 size, u16 destOffset)
{
u16 paletteOffset;
s8 cursor;
if (IsInvalidBg32(bg) == FALSE)
{
paletteOffset = (gGpuBgConfigs2[bg].basePalette * 0x20) + (destOffset * 2);
paletteOffset = (sGpuBgConfigs2[bg].basePalette * 0x20) + (destOffset * 2);
cursor = RequestDma3Copy(src, (void*)(paletteOffset + BG_PLTT), size, 0);
if (cursor == -1)
@@ -455,7 +429,7 @@ u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset)
return -1;
}
gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
return (u8)cursor;
}
@@ -474,7 +448,7 @@ bool8 IsDma3ManagerBusyWithBgCopy(void)
div = i / 0x20;
mod = i % 0x20;
if ((gDmaBusyBitfield[div] & (1 << mod)) != FALSE)
if ((sDmaBusyBitfield[div] & (1 << mod)) != FALSE)
{
reqSpace = CheckForSpaceForDma3Request(i);
if (reqSpace == -1)
@@ -482,7 +456,7 @@ bool8 IsDma3ManagerBusyWithBgCopy(void)
return TRUE;
}
gDmaBusyBitfield[div] &= ~(1 << mod);
sDmaBusyBitfield[div] &= ~(1 << mod);
}
}
@@ -508,7 +482,7 @@ _08001AE4:\n\
sub r0, r5, r0\n\
lsl r0, #24\n\
lsr r0, #24\n\
ldr r1, =gDmaBusyBitfield\n\
ldr r1, =sDmaBusyBitfield\n\
lsr r2, #22\n\
add r4, r2, r1\n\
mov r6, #0x1\n\
@@ -614,7 +588,7 @@ u16 GetBgAttribute(u8 bg, u8 attributeId)
case 9:
return GetBgType(bg);
case 10:
return gGpuBgConfigs2[bg].baseTile;
return sGpuBgConfigs2[bg].baseTile;
default:
return -1;
}
@@ -635,13 +609,13 @@ u32 ChangeBgX(u8 bg, u32 value, u8 op)
{
case 0:
default:
gGpuBgConfigs2[bg].bg_x = value;
sGpuBgConfigs2[bg].bg_x = value;
break;
case 1:
gGpuBgConfigs2[bg].bg_x += value;
sGpuBgConfigs2[bg].bg_x += value;
break;
case 2:
gGpuBgConfigs2[bg].bg_x -= value;
sGpuBgConfigs2[bg].bg_x -= value;
break;
}
@@ -650,23 +624,23 @@ u32 ChangeBgX(u8 bg, u32 value, u8 op)
switch (bg)
{
case 0:
temp1 = gGpuBgConfigs2[0].bg_x >> 0x8;
temp1 = sGpuBgConfigs2[0].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG0HOFS, temp1);
break;
case 1:
temp1 = gGpuBgConfigs2[1].bg_x >> 0x8;
temp1 = sGpuBgConfigs2[1].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG1HOFS, temp1);
break;
case 2:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[2].bg_x >> 0x8;
temp1 = sGpuBgConfigs2[2].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG2HOFS, temp1);
}
else
{
temp1 = gGpuBgConfigs2[2].bg_x >> 0x10;
temp2 = gGpuBgConfigs2[2].bg_x & 0xFFFF;
temp1 = sGpuBgConfigs2[2].bg_x >> 0x10;
temp2 = sGpuBgConfigs2[2].bg_x & 0xFFFF;
SetGpuReg(REG_OFFSET_BG2X_H, temp1);
SetGpuReg(REG_OFFSET_BG2X_L, temp2);
}
@@ -674,20 +648,20 @@ u32 ChangeBgX(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[3].bg_x >> 0x8;
temp1 = sGpuBgConfigs2[3].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG3HOFS, temp1);
}
else if (mode == 2)
{
temp1 = gGpuBgConfigs2[3].bg_x >> 0x10;
temp2 = gGpuBgConfigs2[3].bg_x & 0xFFFF;
temp1 = sGpuBgConfigs2[3].bg_x >> 0x10;
temp2 = sGpuBgConfigs2[3].bg_x & 0xFFFF;
SetGpuReg(REG_OFFSET_BG3X_H, temp1);
SetGpuReg(REG_OFFSET_BG3X_L, temp2);
}
break;
}
return gGpuBgConfigs2[bg].bg_x;
return sGpuBgConfigs2[bg].bg_x;
}
u32 GetBgX(u8 bg)
@@ -696,7 +670,7 @@ u32 GetBgX(u8 bg)
return -1;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return -1;
return gGpuBgConfigs2[bg].bg_x;
return sGpuBgConfigs2[bg].bg_x;
}
u32 ChangeBgY(u8 bg, u32 value, u8 op)
@@ -714,13 +688,13 @@ u32 ChangeBgY(u8 bg, u32 value, u8 op)
{
case 0:
default:
gGpuBgConfigs2[bg].bg_y = value;
sGpuBgConfigs2[bg].bg_y = value;
break;
case 1:
gGpuBgConfigs2[bg].bg_y += value;
sGpuBgConfigs2[bg].bg_y += value;
break;
case 2:
gGpuBgConfigs2[bg].bg_y -= value;
sGpuBgConfigs2[bg].bg_y -= value;
break;
}
@@ -729,23 +703,23 @@ u32 ChangeBgY(u8 bg, u32 value, u8 op)
switch (bg)
{
case 0:
temp1 = gGpuBgConfigs2[0].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[0].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG0VOFS, temp1);
break;
case 1:
temp1 = gGpuBgConfigs2[1].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[1].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG1VOFS, temp1);
break;
case 2:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[2].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[2].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG2VOFS, temp1);
}
else
{
temp1 = gGpuBgConfigs2[2].bg_y >> 0x10;
temp2 = gGpuBgConfigs2[2].bg_y & 0xFFFF;
temp1 = sGpuBgConfigs2[2].bg_y >> 0x10;
temp2 = sGpuBgConfigs2[2].bg_y & 0xFFFF;
SetGpuReg(REG_OFFSET_BG2Y_H, temp1);
SetGpuReg(REG_OFFSET_BG2Y_L, temp2);
}
@@ -753,20 +727,20 @@ u32 ChangeBgY(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[3].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[3].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG3VOFS, temp1);
}
else if (mode == 2)
{
temp1 = gGpuBgConfigs2[3].bg_y >> 0x10;
temp2 = gGpuBgConfigs2[3].bg_y & 0xFFFF;
temp1 = sGpuBgConfigs2[3].bg_y >> 0x10;
temp2 = sGpuBgConfigs2[3].bg_y & 0xFFFF;
SetGpuReg(REG_OFFSET_BG3Y_H, temp1);
SetGpuReg(REG_OFFSET_BG3Y_L, temp2);
}
break;
}
return gGpuBgConfigs2[bg].bg_y;
return sGpuBgConfigs2[bg].bg_y;
}
u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
@@ -784,13 +758,13 @@ u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
{
case 0:
default:
gGpuBgConfigs2[bg].bg_y = value;
sGpuBgConfigs2[bg].bg_y = value;
break;
case 1:
gGpuBgConfigs2[bg].bg_y += value;
sGpuBgConfigs2[bg].bg_y += value;
break;
case 2:
gGpuBgConfigs2[bg].bg_y -= value;
sGpuBgConfigs2[bg].bg_y -= value;
break;
}
@@ -799,24 +773,24 @@ u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
switch (bg)
{
case 0:
temp1 = gGpuBgConfigs2[0].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[0].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG0VOFS, temp1);
break;
case 1:
temp1 = gGpuBgConfigs2[1].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[1].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG1VOFS, temp1);
break;
case 2:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[2].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[2].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG2VOFS, temp1);
}
else
{
temp1 = gGpuBgConfigs2[2].bg_y >> 0x10;
temp2 = gGpuBgConfigs2[2].bg_y & 0xFFFF;
temp1 = sGpuBgConfigs2[2].bg_y >> 0x10;
temp2 = sGpuBgConfigs2[2].bg_y & 0xFFFF;
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_H, temp1);
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_L, temp2);
}
@@ -824,20 +798,20 @@ u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
temp1 = gGpuBgConfigs2[3].bg_y >> 0x8;
temp1 = sGpuBgConfigs2[3].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG3VOFS, temp1);
}
else if (mode == 2)
{
temp1 = gGpuBgConfigs2[3].bg_y >> 0x10;
temp2 = gGpuBgConfigs2[3].bg_y & 0xFFFF;
temp1 = sGpuBgConfigs2[3].bg_y >> 0x10;
temp2 = sGpuBgConfigs2[3].bg_y & 0xFFFF;
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_H, temp1);
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_L, temp2);
}
break;
}
return gGpuBgConfigs2[bg].bg_y;
return sGpuBgConfigs2[bg].bg_y;
}
u32 GetBgY(u8 bg)
@@ -846,7 +820,7 @@ u32 GetBgY(u8 bg)
return -1;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return -1;
return gGpuBgConfigs2[bg].bg_y;
return sGpuBgConfigs2[bg].bg_y;
}
void SetBgAffine(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
@@ -933,7 +907,7 @@ void SetBgTilemapBuffer(u8 bg, void *tilemap)
{
if (IsInvalidBg32(bg) == FALSE && GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) != 0x0)
{
gGpuBgConfigs2[bg].tilemap = tilemap;
sGpuBgConfigs2[bg].tilemap = tilemap;
}
}
@@ -941,7 +915,7 @@ void UnsetBgTilemapBuffer(u8 bg)
{
if (IsInvalidBg32(bg) == FALSE && GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) != 0x0)
{
gGpuBgConfigs2[bg].tilemap = NULL;
sGpuBgConfigs2[bg].tilemap = NULL;
}
}
@@ -951,20 +925,20 @@ void* GetBgTilemapBuffer(u8 bg)
return NULL;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return NULL;
return gGpuBgConfigs2[bg].tilemap;
return sGpuBgConfigs2[bg].tilemap;
}
void CopyToBgTilemapBuffer(u8 bg, void *src, u16 mode, u16 destOffset)
void CopyToBgTilemapBuffer(u8 bg, const void *src, u16 mode, u16 destOffset)
{
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
if (mode != 0)
{
CpuCopy16(src, (void *)(gGpuBgConfigs2[bg].tilemap + (destOffset * 2)), mode);
CpuCopy16(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2)), mode);
}
else
{
LZ77UnCompWram(src, (void *)(gGpuBgConfigs2[bg].tilemap + (destOffset * 2)));
LZ77UnCompWram(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2)));
}
}
}
@@ -987,7 +961,7 @@ void CopyBgTilemapBufferToVram(u8 bg)
sizeToLoad = 0;
break;
}
LoadBgVram(bg, gGpuBgConfigs2[bg].tilemap, sizeToLoad, 0, 2);
LoadBgVram(bg, sGpuBgConfigs2[bg].tilemap, sizeToLoad, 0, 2);
}
}
@@ -1008,7 +982,7 @@ void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u
{
for (destX16 = destX; destX16 < (destX + width); destX16++)
{
((u16*)gGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *((u16*)srcCopy)++;
((u16*)sGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *((u16*)srcCopy)++;
}
}
break;
@@ -1019,7 +993,7 @@ void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u
{
for (destX16 = destX; destX16 < (destX + width); destX16++)
{
((u8*)gGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *((u8*)srcCopy)++;
((u8*)sGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *((u8*)srcCopy)++;
}
}
break;
@@ -1056,7 +1030,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, void* src, u8 srcX, u8 srcY, u8 srcWid
{
for (destX16 = destX; destX16 < (destX + rectWidth); destX16++)
{
CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)gGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)sGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
}
}
break;
@@ -1067,7 +1041,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, void* src, u8 srcX, u8 srcY, u8 srcWid
{
for (destX16 = destX; destX16 < (destX + rectWidth); destX16++)
{
CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)gGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)sGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
}
}
break;
@@ -1195,7 +1169,7 @@ _080025F8:\n\
bge _0800265A\n\
ldr r2, [sp, #0x4]\n\
lsl r0, r2, #4\n\
ldr r1, =gGpuBgConfigs2+4\n\
ldr r1, =sGpuBgConfigs2+4\n\
add r0, r1\n\
mov r10, r0\n\
ldr r7, [sp, #0x20]\n\
@@ -1267,7 +1241,7 @@ _08002674:\n\
sub r2, r7, r2\n\
str r2, [sp, #0x34]\n\
str r0, [sp, #0x38]\n\
ldr r7, =gGpuBgConfigs2+4\n\
ldr r7, =sGpuBgConfigs2+4\n\
mov r10, r7\n\
ldr r0, [sp, #0x4]\n\
lsl r0, #4\n\
@@ -1337,7 +1311,7 @@ void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width,
{
for (x16 = x; x16 < (x + width); x16++)
{
((u16*)gGpuBgConfigs2[bg].tilemap)[((y16 * 0x20) + x16)] = tileNum;
((u16*)sGpuBgConfigs2[bg].tilemap)[((y16 * 0x20) + x16)] = tileNum;
}
}
break;
@@ -1347,7 +1321,7 @@ void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width,
{
for (x16 = x; x16 < (x + width); x16++)
{
((u8*)gGpuBgConfigs2[bg].tilemap)[((y16 * mode) + x16)] = tileNum;
((u8*)sGpuBgConfigs2[bg].tilemap)[((y16 * mode) + x16)] = tileNum;
}
}
break;
@@ -1382,7 +1356,7 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
{
for (x16 = x; x16 < (x + width); x16++)
{
CopyTileMapEntry(&firstTileNum, &((u16*)gGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(x16, y16, attribute, mode, mode2)], paletteSlot, 0, 0);
CopyTileMapEntry(&firstTileNum, &((u16*)sGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(x16, y16, attribute, mode, mode2)], paletteSlot, 0, 0);
firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF);
}
}
@@ -1393,7 +1367,7 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
{
for (x16 = x; x16 < (x + width); x16++)
{
((u8*)gGpuBgConfigs2[bg].tilemap)[(y16 * mode3) + x16] = firstTileNum;
((u8*)sGpuBgConfigs2[bg].tilemap)[(y16 * mode3) + x16] = firstTileNum;
firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF);
}
}
@@ -1625,9 +1599,9 @@ bool32 IsInvalidBg32(u8 bg)
bool32 IsTileMapOutsideWram(u8 bg)
{
if (gGpuBgConfigs2[bg].tilemap > (void*)IWRAM_END)
if (sGpuBgConfigs2[bg].tilemap > (void*)IWRAM_END)
return TRUE;
if (gGpuBgConfigs2[bg].tilemap == 0x0)
if (sGpuBgConfigs2[bg].tilemap == 0x0)
return TRUE;
return FALSE;
}

View File

@@ -19,7 +19,6 @@ extern struct BattleEnigmaBerry gEnigmaBerries[];
extern u16 gBattleMovePower;
extern u16 gTrainerBattleOpponent_A;
u8 CountAliveMonsInBattle(u8);
bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank);
extern const struct BattleMove gBattleMoves[];

View File

@@ -4,14 +4,13 @@
#include "window.h"
#include "text_window.h"
#include "string_util.h"
#include "menu.h"
#define MAX_COINS 9999
EWRAM_DATA u8 sCoinsWindowId = 0;
extern s32 GetStringRightAlignXOffset(u8 fontId, u8 *str, s32 totalWidth);
extern void SetWindowTemplateFields(struct WindowTemplate* template, u8 priority, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 palNum, u16 baseBlock);
extern void SetWindowBorderStyle(u8 windowId, bool8 copyToVram, s16 tileStart, s8 palette);
extern void sub_819746C(u8 windowId, bool8 copyToVram);
extern const u8 gText_Coins[];

View File

@@ -14,7 +14,7 @@ void ClearDma3Requests(void)
gDma3Requests[i].src = 0;
gDma3Requests[i].dest = 0;
}
gDma3ManagerLocked = FALSE;
}
@@ -24,7 +24,7 @@ void ProcessDma3Requests(void)
// NOTE: the fillerA member of the DMA struct is actually u32 value;
// NOTE: gUnknown_0300001C is just a pointer inside the gDma3Requests structure, not a true symbol; feel free to remove
u16 total_size;
if (gDma3ManagerLocked)
return;
@@ -34,7 +34,7 @@ void ProcessDma3Requests(void)
while (gDma3Requests[gDma3RequestCursor].size)
{
total_size += gDma3Requests[gDma3RequestCursor].size;
if (total_size > 0xA000)
return; // don't do too much at once
@@ -90,14 +90,14 @@ void ProcessDma3Requests(void)
}
DmaFill16(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size);
break;
}
gDma3Requests[gDma3RequestCursor].src = 0;
gDma3Requests[gDma3RequestCursor].dest = 0;
}
gDma3Requests[gDma3RequestCursor].src = NULL;
gDma3Requests[gDma3RequestCursor].dest = NULL;
gDma3Requests[gDma3RequestCursor].size = 0;
gDma3Requests[gDma3RequestCursor].mode = 0;
gDma3Requests[gDma3RequestCursor].value = 0;
gDma3RequestCursor++;
if (gDma3RequestCursor >= 128) // loop back to the first DMA request
gDma3RequestCursor = 0;
}
@@ -419,13 +419,13 @@ _08000E46:\n\
}
#endif
int RequestDma3Copy(void *src, void *dest, u16 size, u8 mode)
int RequestDma3Copy(const void *src, void *dest, u16 size, u8 mode)
{
int cursor;
int var = 0;
gDma3ManagerLocked = 1;
cursor = gDma3RequestCursor;
while(1)
{
@@ -434,12 +434,12 @@ int RequestDma3Copy(void *src, void *dest, u16 size, u8 mode)
gDma3Requests[cursor].src = src;
gDma3Requests[cursor].dest = dest;
gDma3Requests[cursor].size = size;
if(mode == 1)
gDma3Requests[cursor].mode = mode;
else
gDma3Requests[cursor].mode = 3;
gDma3ManagerLocked = FALSE;
return (s16)cursor;
}
@@ -460,10 +460,10 @@ int RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
{
int cursor;
int var = 0;
cursor = gDma3RequestCursor;
gDma3ManagerLocked = 1;
while(1)
{
if(!gDma3Requests[cursor].size)
@@ -477,7 +477,7 @@ int RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
gDma3Requests[cursor].mode = 2;
else
gDma3Requests[cursor].mode = 4;
gDma3ManagerLocked = FALSE;
return (s16)cursor;
}
@@ -503,9 +503,9 @@ int CheckForSpaceForDma3Request(s16 index)
for (; current < 0x80; current ++)
if (gDma3Requests[current].size)
return -1;
return 0;
}
}
if (gDma3Requests[index].size)
return -1;

893
src/egg_hatch.c Normal file
View File

@@ -0,0 +1,893 @@
#include "global.h"
#include "pokemon.h"
#include "pokedex.h"
#include "items.h"
#include "script.h"
#include "decompress.h"
#include "task.h"
#include "palette.h"
#include "main.h"
#include "event_data.h"
#include "sound.h"
#include "songs.h"
#include "text.h"
#include "text_window.h"
#include "string_util.h"
#include "menu.h"
#include "trig.h"
#include "rng.h"
#include "malloc.h"
#include "dma3.h"
#include "gpu_regs.h"
#include "bg.h"
#include "m4a.h"
#include "window.h"
#include "abilities.h"
#include "battle.h" // to get rid of later
struct EggHatchData
{
u8 eggSpriteID;
u8 pokeSpriteID;
u8 CB2_state;
u8 CB2_PalCounter;
u8 eggPartyID;
u8 unused_5;
u8 unused_6;
u8 eggShardVelocityID;
u8 windowId;
u8 unused_9;
u8 unused_A;
u16 species;
struct TextColor textColor;
};
extern struct SpriteTemplate gUnknown_0202499C;
extern void (*gFieldCallback)(void);
extern const struct CompressedSpriteSheet gMonFrontPicTable[];
extern const u8 gUnknown_08C00000[];
extern const u8 gUnknown_08C00524[];
extern const u8 gUnknown_08C004E0[];
extern const u16 gUnknown_08DD7300[]; // palette, gameboy advance
extern const u32 gUnknown_08DD7360[]; // tileset gameboy advance
extern const u32 gUnknown_08331F60[]; // tilemap gameboy circle
extern const u8 gText_HatchedFromEgg[];
extern const u8 gText_NickHatchPrompt[];
extern u8* GetMonNick(struct Pokemon* mon, u8* dst);
extern u8* GetBoxMonNick(struct BoxPokemon* boxMon, u8* dst);
extern u8 sav1_map_get_name(void);
extern s8 sub_8198C58(void);
extern void sub_81DB5E8(u8* str1, u8* str2, u8);
extern void sub_806A068(u16, u8);
extern void fade_screen(u8, u8);
extern void overworld_free_bg_tilemaps(void);
extern void sub_80AF168(void);
extern void init_uns_table_pokemon_copy(void);
extern void sub_805F094(void);
extern void remove_some_task(void);
extern void reset_temp_tile_data_buffers(void);
extern void c2_exit_to_overworld_2_switch(void);
extern void play_some_sound(void);
extern void copy_decompressed_tile_data_to_vram_autofree(u8 bg_id, const void* src, u16 size, u16 offset, u8 mode);
extern void CreateYesNoMenu(const struct WindowTemplate*, u16, u8, u8);
extern void DoNamingScreen(u8, const u8*, u16, u8, u32, MainCallback);
extern void AddTextPrinterParametrized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, struct TextColor* colors, s8 speed, u8 *str);
extern u16 sub_80D22D0(void);
extern u8 sub_80C7050(u8);
static void Task_EggHatch(u8 taskID);
static void CB2_EggHatch_0(void);
static void CB2_EggHatch_1(void);
static void SpriteCB_Egg_0(struct Sprite* sprite);
static void SpriteCB_Egg_1(struct Sprite* sprite);
static void SpriteCB_Egg_2(struct Sprite* sprite);
static void SpriteCB_Egg_3(struct Sprite* sprite);
static void SpriteCB_Egg_4(struct Sprite* sprite);
static void SpriteCB_Egg_5(struct Sprite* sprite);
static void SpriteCB_EggShard(struct Sprite* sprite);
static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed);
static void CreateRandomEggShardSprite(void);
static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex);
// IWRAM bss
static IWRAM_DATA struct EggHatchData* sEggHatchData;
// rom data
static const u16 sEggPalette[] = INCBIN_U16("graphics/pokemon/palettes/egg_palette.gbapal");
static const u8 sEggHatchTiles[] = INCBIN_U8("graphics/misc/egg_hatch.4bpp");
static const u8 sEggShardTiles[] = INCBIN_U8("graphics/misc/egg_shard.4bpp");
static const struct OamData sOamData_EggHatch =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 2,
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_EggHatch0[] =
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggHatch1[] =
{
ANIMCMD_FRAME(16, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggHatch2[] =
{
ANIMCMD_FRAME(32, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggHatch3[] =
{
ANIMCMD_FRAME(48, 5),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_EggHatch[] =
{
sSpriteAnim_EggHatch0,
sSpriteAnim_EggHatch1,
sSpriteAnim_EggHatch2,
sSpriteAnim_EggHatch3,
};
static const struct SpriteSheet sEggHatch_Sheet =
{
.data = sEggHatchTiles,
.size = 2048,
.tag = 12345,
};
static const struct SpriteSheet sEggShards_Sheet =
{
.data = sEggShardTiles,
.size = 128,
.tag = 23456,
};
static const struct SpritePalette sEgg_SpritePalette =
{
.data = sEggPalette,
.tag = 54321
};
static const struct SpriteTemplate sSpriteTemplate_EggHatch =
{
.tileTag = 12345,
.paletteTag = 54321,
.oam = &sOamData_EggHatch,
.anims = sSpriteAnimTable_EggHatch,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
static const struct OamData sOamData_EggShard =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 0,
.tileNum = 0,
.priority = 2,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_EggShard0[] =
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggShard1[] =
{
ANIMCMD_FRAME(1, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggShard2[] =
{
ANIMCMD_FRAME(2, 5),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_EggShard3[] =
{
ANIMCMD_FRAME(3, 5),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_EggShard[] =
{
sSpriteAnim_EggShard0,
sSpriteAnim_EggShard1,
sSpriteAnim_EggShard2,
sSpriteAnim_EggShard3,
};
static const struct SpriteTemplate sSpriteTemplate_EggShard =
{
.tileTag = 23456,
.paletteTag = 54321,
.oam = &sOamData_EggShard,
.anims = sSpriteAnimTable_EggShard,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_EggShard
};
static const struct BgTemplate sBgTemplates_EggHatch[2] =
{
{
.bg = 0,
.charBaseIndex = 2,
.mapBaseIndex = 24,
.screenSize = 3,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
},
{
.bg = 1,
.charBaseIndex = 0,
.mapBaseIndex = 8,
.screenSize = 1,
.paletteMode = 0,
.priority = 2,
.baseTile = 0
},
};
static const struct WindowTemplate sWinTemplates_EggHatch[2] =
{
{0, 2, 0xF, 0x1A, 4, 0, 0x40},
DUMMY_WIN_TEMPLATE
};
static const struct WindowTemplate sYesNoWinTemplate =
{
0, 0x15, 9, 5, 4, 0xF, 0x1A8
};
static const s16 sEggShardVelocities[][2] =
{
{Q_8_8(-1.5), Q_8_8(-3.75)},
{Q_8_8(-5), Q_8_8(-3)},
{Q_8_8(3.5), Q_8_8(-3)},
{Q_8_8(-4), Q_8_8(-3.75)},
{Q_8_8(2), Q_8_8(-1.5)},
{Q_8_8(-0.5), Q_8_8(-6.75)},
{Q_8_8(5), Q_8_8(-2.25)},
{Q_8_8(-1.5), Q_8_8(-3.75)},
{Q_8_8(4.5), Q_8_8(-1.5)},
{Q_8_8(-1), Q_8_8(-6.75)},
{Q_8_8(4), Q_8_8(-2.25)},
{Q_8_8(-3.5), Q_8_8(-3.75)},
{Q_8_8(1), Q_8_8(-1.5)},
{Q_8_8(-3.515625), Q_8_8(-6.75)},
{Q_8_8(4.5), Q_8_8(-2.25)},
{Q_8_8(-0.5), Q_8_8(-7.5)},
{Q_8_8(1), Q_8_8(-4.5)},
{Q_8_8(-2.5), Q_8_8(-2.25)},
{Q_8_8(2.5), Q_8_8(-7.5)},
};
// code
static void CreatedHatchedMon(struct Pokemon *egg, struct Pokemon *temp)
{
u16 species;
u32 personality, pokerus;
u8 i, friendship, language, gameMet, markings, obedience;
u16 moves[4];
u32 ivs[6];
species = GetMonData(egg, MON_DATA_SPECIES);
for (i = 0; i < 4; i++)
{
moves[i] = GetMonData(egg, MON_DATA_MOVE1 + i);
}
personality = GetMonData(egg, MON_DATA_PERSONALITY);
for (i = 0; i < 6; i++)
{
ivs[i] = GetMonData(egg, MON_DATA_HP_IV + i);
}
language = GetMonData(egg, MON_DATA_LANGUAGE);
gameMet = GetMonData(egg, MON_DATA_MET_GAME);
markings = GetMonData(egg, MON_DATA_MARKINGS);
pokerus = GetMonData(egg, MON_DATA_POKERUS);
obedience = GetMonData(egg, MON_DATA_OBEDIENCE);
CreateMon(temp, species, 5, 32, TRUE, personality, 0, 0);
for (i = 0; i < 4; i++)
{
SetMonData(temp, MON_DATA_MOVE1 + i, &moves[i]);
}
for (i = 0; i < 6; i++)
{
SetMonData(temp, MON_DATA_HP_IV + i, &ivs[i]);
}
language = GAME_LANGUAGE;
SetMonData(temp, MON_DATA_LANGUAGE, &language);
SetMonData(temp, MON_DATA_MET_GAME, &gameMet);
SetMonData(temp, MON_DATA_MARKINGS, &markings);
friendship = 120;
SetMonData(temp, MON_DATA_FRIENDSHIP, &friendship);
SetMonData(temp, MON_DATA_POKERUS, &pokerus);
SetMonData(temp, MON_DATA_OBEDIENCE, &obedience);
*egg = *temp;
}
static void AddHatchedMonToParty(u8 id)
{
u8 isEgg = 0x46; // ?
u16 pokeNum;
u8 name[12];
u16 ball;
u16 caughtLvl;
u8 mapNameID;
struct Pokemon* mon = &gPlayerParty[id];
CreatedHatchedMon(mon, &gEnemyParty[0]);
SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
pokeNum = GetMonData(mon, MON_DATA_SPECIES);
GetSpeciesName(name, pokeNum);
SetMonData(mon, MON_DATA_NICKNAME, name);
pokeNum = SpeciesToNationalPokedexNum(pokeNum);
GetSetPokedexFlag(pokeNum, FLAG_SET_SEEN);
GetSetPokedexFlag(pokeNum, FLAG_SET_CAUGHT);
GetMonNick(mon, gStringVar1);
ball = ITEM_POKE_BALL;
SetMonData(mon, MON_DATA_POKEBALL, &ball);
caughtLvl = 0;
SetMonData(mon, MON_DATA_MET_LEVEL, &caughtLvl);
mapNameID = sav1_map_get_name();
SetMonData(mon, MON_DATA_MET_LOCATION, &mapNameID);
MonRestorePP(mon);
CalculateMonStats(mon);
}
void ScriptHatchMon(void)
{
AddHatchedMonToParty(gSpecialVar_0x8004);
}
static bool8 sub_807158C(struct DaycareData* daycare, u8 daycareId)
{
u8 nick[0x20];
struct DaycareMon* daycareMon = &daycare->mons[daycareId];
GetBoxMonNick(&daycareMon->mon, nick);
if (daycareMon->mail.itemId != 0
&& (StringCompareWithoutExtCtrlCodes(nick, daycareMon->monName) != 0
|| StringCompareWithoutExtCtrlCodes(gSaveBlock2Ptr->playerName, daycareMon->OT_name) != 0))
{
StringCopy(gStringVar1, nick);
sub_81DB5E8(gStringVar2, daycareMon->OT_name, daycareMon->language_maybe);
sub_81DB5E8(gStringVar3, daycareMon->monName, daycareMon->unknown);
return TRUE;
}
return FALSE;
}
bool8 sub_8071614(void)
{
return sub_807158C(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
}
static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc)
{
u8 r5 = 0;
u8 spriteID = 0;
struct Pokemon* mon = NULL;
if (a0 == 0)
{
mon = &gPlayerParty[pokeID];
r5 = 1;
}
if (a0 == 1)
{
mon = &gPlayerParty[pokeID];
r5 = 3;
}
switch (switchID)
{
case 0:
{
u16 species = GetMonData(mon, MON_DATA_SPECIES);
u32 pid = GetMonData(mon, MON_DATA_PERSONALITY);
HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
gBattleSpritesGfx->sprites[(a0 * 2) + 1],
species, pid);
LoadCompressedObjectPalette(sub_806E794(mon));
*speciesLoc = species;
}
break;
case 1:
sub_806A068(sub_806E794(mon)->tag, r5);
spriteID = CreateSprite(&gUnknown_0202499C, 120, 75, 6);
gSprites[spriteID].invisible = 1;
gSprites[spriteID].callback = SpriteCallbackDummy;
break;
}
return spriteID;
}
static void VBlankCB_EggHatch(void)
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
static void EggHatch(void)
{
ScriptContext2_Enable();
CreateTask(Task_EggHatch, 10);
fade_screen(1, 0);
}
static void Task_EggHatch(u8 taskID)
{
if (!gPaletteFade.active)
{
overworld_free_bg_tilemaps();
SetMainCallback2(CB2_EggHatch_0);
gFieldCallback = sub_80AF168;
DestroyTask(taskID);
}
}
static void CB2_EggHatch_0(void)
{
switch (gMain.state)
{
case 0:
SetGpuReg(REG_OFFSET_DISPCNT, 0);
sEggHatchData = Alloc(sizeof(struct EggHatchData));
init_uns_table_pokemon_copy();
sEggHatchData->eggPartyID = gSpecialVar_0x8004;
sEggHatchData->eggShardVelocityID = 0;
SetVBlankCallback(VBlankCB_EggHatch);
gSpecialVar_0x8005 = GetCurrentMapMusic();
reset_temp_tile_data_buffers();
ResetBgsAndClearDma3BusyFlags(0);
InitBgsFromTemplates(0, sBgTemplates_EggHatch, ARRAY_COUNT(sBgTemplates_EggHatch));
ChangeBgX(1, 0, 0);
ChangeBgY(1, 0, 0);
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 2);
SetBgTilemapBuffer(1, Alloc(0x1000));
SetBgTilemapBuffer(0, Alloc(0x2000));
DeactivateAllTextPrinters();
ResetPaletteFade();
FreeAllSpritePalettes();
ResetSpriteData();
ResetTasks();
remove_some_task();
m4aSoundVSyncOn();
gMain.state++;
break;
case 1:
InitWindows(sWinTemplates_EggHatch);
sEggHatchData->windowId = 0;
gMain.state++;
break;
case 2:
copy_decompressed_tile_data_to_vram_autofree(0, gUnknown_08C00000, 0, 0, 0);
CopyToBgTilemapBuffer(0, gUnknown_08C00524, 0, 0);
LoadCompressedPalette(gUnknown_08C004E0, 0, 0x20);
gMain.state++;
break;
case 3:
LoadSpriteSheet(&sEggHatch_Sheet);
LoadSpriteSheet(&sEggShards_Sheet);
LoadSpritePalette(&sEgg_SpritePalette);
gMain.state++;
break;
case 4:
CopyBgTilemapBufferToVram(0);
AddHatchedMonToParty(sEggHatchData->eggPartyID);
gMain.state++;
break;
case 5:
EggHatchCreateMonSprite(0, 0, sEggHatchData->eggPartyID, &sEggHatchData->species);
gMain.state++;
break;
case 6:
sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(0, 1, sEggHatchData->eggPartyID, &sEggHatchData->species);
gMain.state++;
break;
case 7:
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
LoadPalette(gUnknown_08DD7300, 0x10, 0xA0);
LoadBgTiles(1, gUnknown_08DD7360, 0x1420, 0);
CopyToBgTilemapBuffer(1, gUnknown_08331F60, 0x1000, 0);
CopyBgTilemapBufferToVram(1);
gMain.state++;
break;
case 8:
SetMainCallback2(CB2_EggHatch_1);
sEggHatchData->CB2_state = 0;
break;
}
RunTasks();
RunTextPrinters();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
static void EggHatchSetMonNickname(void)
{
SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
sub_805F094();
Free(sEggHatchData);
SetMainCallback2(c2_exit_to_overworld_2_switch);
}
static void Task_EggHatchPlayBGM(u8 taskID)
{
if (gTasks[taskID].data[0] == 0)
{
StopMapMusic();
play_some_sound();
}
if (gTasks[taskID].data[0] == 1)
PlayBGM(376);
if (gTasks[taskID].data[0] > 60)
{
PlayBGM(377);
DestroyTask(taskID);
// UB: task is destroyed, yet the value is incremented
}
gTasks[taskID].data[0]++;
}
static void CB2_EggHatch_1(void)
{
u16 species;
u8 gender;
u32 personality;
switch (sEggHatchData->CB2_state)
{
case 0:
BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
sEggHatchData->eggSpriteID = CreateSprite(&sSpriteTemplate_EggHatch, 120, 75, 5);
ShowBg(0);
ShowBg(1);
sEggHatchData->CB2_state++;
CreateTask(Task_EggHatchPlayBGM, 5);
break;
case 1:
if (!gPaletteFade.active)
{
FillWindowPixelBuffer(sEggHatchData->windowId, 0);
sEggHatchData->CB2_PalCounter = 0;
sEggHatchData->CB2_state++;
}
break;
case 2:
if (++sEggHatchData->CB2_PalCounter > 30)
{
sEggHatchData->CB2_state++;
gSprites[sEggHatchData->eggSpriteID].callback = SpriteCB_Egg_0;
}
break;
case 3:
if (gSprites[sEggHatchData->eggSpriteID].callback == SpriteCallbackDummy)
{
species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
DoMonFrontSpriteAnimation(&gSprites[sEggHatchData->pokeSpriteID], species, FALSE, 1);
sEggHatchData->CB2_state++;
}
break;
case 4:
if (gSprites[sEggHatchData->pokeSpriteID].callback == SpriteCallbackDummy)
{
sEggHatchData->CB2_state++;
}
break;
case 5:
GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_HatchedFromEgg);
EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 3, 0xFF);
PlayFanfare(371);
sEggHatchData->CB2_state++;
PutWindowTilemap(sEggHatchData->windowId);
CopyWindowToVram(sEggHatchData->windowId, 3);
break;
case 6:
if (IsFanfareTaskInactive())
sEggHatchData->CB2_state++;
break;
case 7:
if (IsFanfareTaskInactive())
sEggHatchData->CB2_state++;
break;
case 8:
GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_NickHatchPrompt);
EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 2, 1);
sEggHatchData->CB2_state++;
break;
case 9:
if (!IsTextPrinterActive(sEggHatchData->windowId))
{
sub_809882C(sEggHatchData->windowId, 0x140, 0xE0);
CreateYesNoMenu(&sYesNoWinTemplate, 0x140, 0xE, 0);
sEggHatchData->CB2_state++;
}
break;
case 10:
switch (sub_8198C58())
{
case 0:
GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar3);
species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
gender = GetMonGender(&gPlayerParty[sEggHatchData->eggPartyID]);
personality = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_PERSONALITY, 0);
DoNamingScreen(3, gStringVar3, species, gender, personality, EggHatchSetMonNickname);
break;
case 1:
case -1:
sEggHatchData->CB2_state++;
}
break;
case 11:
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
sEggHatchData->CB2_state++;
break;
case 12:
if (!gPaletteFade.active)
{
sub_805F094();
RemoveWindow(sEggHatchData->windowId);
UnsetBgTilemapBuffer(0);
UnsetBgTilemapBuffer(1);
Free(sEggHatchData);
SetMainCallback2(c2_exit_to_overworld_2_switch);
}
break;
}
RunTasks();
RunTextPrinters();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
static void SpriteCB_Egg_0(struct Sprite* sprite)
{
if (++sprite->data0 > 20)
{
sprite->callback = SpriteCB_Egg_1;
sprite->data0 = 0;
}
else
{
sprite->data1 = (sprite->data1 + 20) & 0xFF;
sprite->pos2.x = Sin(sprite->data1, 1);
if (sprite->data0 == 15)
{
PlaySE(SE_BOWA);
StartSpriteAnim(sprite, 1);
CreateRandomEggShardSprite();
}
}
}
static void SpriteCB_Egg_1(struct Sprite* sprite)
{
if (++sprite->data2 > 30)
{
if (++sprite->data0 > 20)
{
sprite->callback = SpriteCB_Egg_2;
sprite->data0 = 0;
sprite->data2 = 0;
}
else
{
sprite->data1 = (sprite->data1 + 20) & 0xFF;
sprite->pos2.x = Sin(sprite->data1, 2);
if (sprite->data0 == 15)
{
PlaySE(SE_BOWA);
StartSpriteAnim(sprite, 2);
}
}
}
}
static void SpriteCB_Egg_2(struct Sprite* sprite)
{
if (++sprite->data2 > 30)
{
if (++sprite->data0 > 38)
{
u16 species;
sprite->callback = SpriteCB_Egg_3;
sprite->data0 = 0;
species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
gSprites[sEggHatchData->pokeSpriteID].pos2.x = 0;
gSprites[sEggHatchData->pokeSpriteID].pos2.y = 0;
}
else
{
sprite->data1 = (sprite->data1 + 20) & 0xFF;
sprite->pos2.x = Sin(sprite->data1, 2);
if (sprite->data0 == 15)
{
PlaySE(SE_BOWA);
StartSpriteAnim(sprite, 2);
CreateRandomEggShardSprite();
CreateRandomEggShardSprite();
}
if (sprite->data0 == 30)
PlaySE(SE_BOWA);
}
}
}
static void SpriteCB_Egg_3(struct Sprite* sprite)
{
if (++sprite->data0 > 50)
{
sprite->callback = SpriteCB_Egg_4;
sprite->data0 = 0;
}
}
static void SpriteCB_Egg_4(struct Sprite* sprite)
{
s16 i;
if (sprite->data0 == 0)
BeginNormalPaletteFade(-1, -1, 0, 0x10, 0xFFFF);
if (sprite->data0 < 4u)
{
for (i = 0; i <= 3; i++)
CreateRandomEggShardSprite();
}
sprite->data0++;
if (!gPaletteFade.active)
{
PlaySE(SE_TAMAGO);
sprite->invisible = 1;
sprite->callback = SpriteCB_Egg_5;
sprite->data0 = 0;
}
}
static void SpriteCB_Egg_5(struct Sprite* sprite)
{
if (sprite->data0 == 0)
{
gSprites[sEggHatchData->pokeSpriteID].invisible = 0;
StartSpriteAffineAnim(&gSprites[sEggHatchData->pokeSpriteID], 1);
}
if (sprite->data0 == 8)
BeginNormalPaletteFade(-1, -1, 0x10, 0, 0xFFFF);
if (sprite->data0 <= 9)
gSprites[sEggHatchData->pokeSpriteID].pos1.y -= 1;
if (sprite->data0 > 40)
sprite->callback = SpriteCallbackDummy;
sprite->data0++;
}
static void SpriteCB_EggShard(struct Sprite* sprite)
{
sprite->data4 += sprite->data1;
sprite->data5 += sprite->data2;
sprite->pos2.x = sprite->data4 / 256;
sprite->pos2.y = sprite->data5 / 256;
sprite->data2 += sprite->data3;
if (sprite->pos1.y + sprite->pos2.y > sprite->pos1.y + 20 && sprite->data2 > 0)
DestroySprite(sprite);
}
static void CreateRandomEggShardSprite(void)
{
u16 spriteAnimIndex;
s16 velocity1 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][0];
s16 velocity2 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][1];
sEggHatchData->eggShardVelocityID++;
spriteAnimIndex = Random() % 4;
CreateEggShardSprite(120, 60, velocity1, velocity2, 100, spriteAnimIndex);
}
static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex)
{
u8 spriteID = CreateSprite(&sSpriteTemplate_EggShard, x, y, 4);
gSprites[spriteID].data1 = data1;
gSprites[spriteID].data2 = data2;
gSprites[spriteID].data3 = data3;
StartSpriteAnim(&gSprites[spriteID], spriteAnimIndex);
}
static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed)
{
FillWindowPixelBuffer(windowId, 0xFF);
sEggHatchData->textColor.fgColor = 0;
sEggHatchData->textColor.bgColor = 5;
sEggHatchData->textColor.shadowColor = 6;
AddTextPrinterParametrized2(windowId, 1, x, y, 0, 0, &sEggHatchData->textColor, speed, string);
}
u8 GetEggStepsToSubtract(void)
{
u8 count, i;
for (count = CalculatePlayerPartyCount(), i = 0; i < count; i++)
{
if (!GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT3))
{
u8 ability = GetMonAbility(&gPlayerParty[i]);
if (ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_FLAME_BODY)
return 2;
}
}
return 1;
}
u16 sub_80722E0(void)
{
u16 value = sub_80D22D0();
value += sub_80C7050(6);
return value;
}

View File

@@ -3413,7 +3413,7 @@ bool8 mss_08062EA4(struct MapObject *mapObject, struct Sprite *sprite)
{
return FALSE;
}
return gUnknown_0850DA64[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), sub_8088E64);
return gUnknown_0850DA64[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), MetatileBehavior_IsPokeGrass);
}
bool8 sub_80925AC(struct MapObject *, struct Sprite *);

363
src/field_special_scene.c Executable file
View File

@@ -0,0 +1,363 @@
#include "global.h"
#include "task.h"
#include "sprite.h"
#include "field_map_obj.h"
#include "songs.h"
#include "sound.h"
#include "palette.h"
#include "script.h"
#include "vars.h"
#include "event_data.h"
#include "main.h"
#define SECONDS(value) ((signed) (60.0 * value + 0.5))
extern u8 GetSSTidalLocation(s8 *, s8 *, s16 *, s16 *); // should be in field_specials.h
extern void warp1_set(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y);
extern bool8 sub_80D3340(u8, u8, u8);
extern bool32 CountSSTidalStep(u16);
extern bool8 exec_movement(u8, u8, u8, u8 *);
extern void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused);
extern void sp13E_warp_to_last_warp(void);
extern void saved_warp2_set(int unused, s8 mapGroup, s8 mapNum, s8 warpId);
extern void sub_80AF8B8(void);
// porthole states
enum
{
INIT_PORTHOLE,
IDLE_CHECK,
EXECUTE_MOVEMENT,
EXIT_PORTHOLE,
};
extern void SetCameraPanning(s16 x, s16 y);
extern void SetCameraPanningCallback(void ( *callback)());
extern void InstallCameraPanAheadCallback();
extern void pal_fill_black(void);
extern void MapGridSetMetatileIdAt(s32 x, s32 y, u16 metatileId);
extern void DrawWholeMapView();
extern s8 gTruckCamera_HorizontalTable[];
extern u8 gUnknown_0858E8AB[];
extern u8 gUnknown_0858E8AD[];
void Task_Truck3(u8);
s16 GetTruckCameraBobbingY(int a1)
{
if (!(a1 % 120))
return -1;
else if ((a1 % 10) <= 4)
return 1;
return 0;
}
s16 GetTruckBoxMovement(int a1) // for the box movement?
{
if (!((a1 + 120) % 180))
return -1;
return 0;
}
// smh STILL BROKEN IN EMERALD
void Task_Truck1(u8 taskId)
{
s16 *data = gTasks[taskId].data;
s16 cameraYpan;
s16 box1 = 0;
s16 box2 = 0;
s16 box3 = 0;
u8 mapNum, mapGroup;
register s16 zero asm("r4");
box1 = GetTruckBoxMovement(data[0] + 30) * 4; // top box.
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3, box1 + 3);
box2 = GetTruckBoxMovement(data[0]) * 2; // bottom left box.
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 0, box2 - 3);
box3 = GetTruckBoxMovement(data[0]) * 4; // bottom right box.
mapNum = gSaveBlock1Ptr->location.mapNum;
mapGroup = gSaveBlock1Ptr->location.mapGroup;
zero = 0;
sub_808E82C(3, mapNum, mapGroup, -3, box3);
if (++data[0] == SECONDS(500)) // this will never run
data[0] = zero; // reset the timer if it gets stuck.
cameraYpan = GetTruckCameraBobbingY(data[0]);
SetCameraPanning(0, cameraYpan);
}
void Task_Truck2(u8 taskId)
{
s16 *data = gTasks[taskId].data;
s16 cameraYpan;
s16 cameraXpan;
s16 box1;
s16 box2;
s16 box3;
data[0]++;
data[2]++;
if (data[0] > 5)
{
data[0] = 0;
data[1]++;
}
if ((u16)data[1] == 19)
{
DestroyTask(taskId);
}
else
{
if (gTruckCamera_HorizontalTable[data[1]] == 2)
gTasks[taskId].func = Task_Truck3;
cameraXpan = gTruckCamera_HorizontalTable[data[1]];
cameraYpan = GetTruckCameraBobbingY(data[2]);
SetCameraPanning(cameraXpan, cameraYpan);
box1 = GetTruckBoxMovement(data[2] + 30) * 4;
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, box1 + 3);
box2 = GetTruckBoxMovement(data[2]) * 2;
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, box2 - 3);
box3 = GetTruckBoxMovement(data[2]) * 4;
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, box3);
}
}
void Task_Truck3(u8 taskId)
{
s16 *data = gTasks[taskId].data;
s16 cameraXpan;
s16 cameraYpan;
data[0]++;
if (data[0] > 5)
{
data[0] = 0;
data[1]++;
}
if ((u16)data[1] == 19)
{
DestroyTask(taskId);
}
else
{
cameraXpan = gTruckCamera_HorizontalTable[data[1]];
cameraYpan = 0;
SetCameraPanning(cameraXpan, 0);
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, cameraYpan + 3);
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, cameraYpan - 3);
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, cameraYpan);
}
}
void Task_HandleTruckSequence(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (data[0])
{
/*
Each case has a timer which is handled with data[1], incrementing
until it reaches the if function's condition, which sets the next task up.
*/
case 0:
data[1]++;
if (data[1] == SECONDS(1.5))
{
SetCameraPanningCallback(NULL);
data[1] = 0; // reset the timer.
data[2] = CreateTask(Task_Truck1, 0xA);
data[0] = 1; // run the next case.
PlaySE(SE_TRACK_MOVE);
}
break;
case 1:
data[1]++;
if (data[1] == SECONDS(2.5))
{
pal_fill_black();
data[1] = 0;
data[0] = 2;
}
break;
case 2:
data[1]++;
if (!gPaletteFade.active && data[1] > SECONDS(5))
{
data[1] = 0;
DestroyTask(data[2]);
data[3] = CreateTask(Task_Truck2, 0xA);
data[0] = 3;
PlaySE(SE_TRACK_STOP);
}
break;
case 3:
if (!gTasks[data[3]].isActive) // is Truck2 no longer active (is Truck3 active?)
{
InstallCameraPanAheadCallback();
data[1] = 0;
data[0] = 4;
}
break;
case 4:
data[1]++;
if (data[1] == 90)
{
PlaySE(SE_TRACK_HAIK);
data[1] = 0;
data[0] = 5;
}
break;
case 5:
data[1]++;
if (data[1] == 120)
{
MapGridSetMetatileIdAt(11, 8, 520);
MapGridSetMetatileIdAt(11, 9, 528);
MapGridSetMetatileIdAt(11, 10, 536);
DrawWholeMapView();
PlaySE(SE_TRACK_DOOR);
DestroyTask(taskId);
ScriptContext2_Disable();
}
break;
}
}
void ExecuteTruckSequence(void)
{
MapGridSetMetatileIdAt(11, 8, 525);
MapGridSetMetatileIdAt(11, 9, 533);
MapGridSetMetatileIdAt(11, 10, 541);
DrawWholeMapView();
ScriptContext2_Enable();
CpuFastFill(0, gPlttBufferFaded, 0x400);
CreateTask(Task_HandleTruckSequence, 0xA);
}
void EndTruckSequence(u8 taskId)
{
if (!FuncIsActiveTask(Task_HandleTruckSequence))
{
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3, 3);
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 0, -3);
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3, 0);
}
}
bool8 sub_80FB59C(void)
{
s8 mapGroup, mapNum;
s16 x, y;
if (GetSSTidalLocation(&mapGroup, &mapNum, &x, &y))
{
return FALSE;
}
else
{
warp1_set(mapGroup, mapNum, -1, x, y);
return TRUE;
}
}
void Task_HandlePorthole(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u16 *var = GetVarPointer(VAR_PORTHOLE);
struct WarpData *location = &gSaveBlock1Ptr->location;
switch (data[0])
{
case INIT_PORTHOLE: // finish fading before making porthole finish.
if (!gPaletteFade.active)
{
data[1] = 0;
data[0] = EXECUTE_MOVEMENT; // execute movement before checking if should be exited. strange?
}
break;
case IDLE_CHECK: // idle and move.
if (gMain.newKeys & A_BUTTON)
data[1] = 1;
if (!sub_80D3340(0xFF, location->mapNum, location->mapGroup))
return;
if (CountSSTidalStep(1) == TRUE)
{
if (*var == 2)
*var = 9;
else
*var = 10;
data[0] = 3;
return;
}
data[0] = 2;
case EXECUTE_MOVEMENT: // execute movement.
if (data[1])
{
data[0] = EXIT_PORTHOLE; // exit porthole.
return;
}
// run this once.
if (*var == 2) // which direction?
{
exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AB);
data[0] = IDLE_CHECK; // run case 1.
}
else
{
exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AD);
data[0] = IDLE_CHECK; // run case 1.
}
break;
case EXIT_PORTHOLE: // exit porthole.
FlagReset(0x4001);
FlagReset(0x4000);
copy_saved_warp2_bank_and_enter_x_to_warp1(0);
sp13E_warp_to_last_warp();
DestroyTask(taskId);
break;
}
}
void sub_80FB6EC(void)
{
u8 spriteId = AddPseudoFieldObject(0x8C, SpriteCallbackDummy, 112, 80, 0);
gSprites[spriteId].coordOffsetEnabled = FALSE;
if (VarGet(0x40B4) == 2)
{
StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(4));
}
else
{
StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(3));
}
}
void sub_80FB768(void)
{
sub_80FB6EC();
gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = TRUE;
pal_fill_black();
CreateTask(Task_HandlePorthole, 80);
ScriptContext2_Enable();
}
void sub_80FB7A4(void)
{
FlagSet(SYS_CRUISE_MODE);
FlagSet(0x4001);
FlagSet(0x4000);
saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
sub_80FB59C();
sub_80AF8B8();
}

View File

@@ -1,4 +1,5 @@
#include "global.h"
#include "gpu_regs.h"
#define GPU_REG_BUF_SIZE 0x60
@@ -14,14 +15,15 @@ static bool8 sShouldSyncRegIE;
static u16 sRegIE;
static void CopyBufferedValueToGpuReg(u8 regOffset);
static void SyncRegIE();
static void SyncRegIE(void);
static void UpdateRegDispstatIntrBits(u16 regIE);
void InitGpuRegManager()
void InitGpuRegManager(void)
{
s32 i;
for (i = 0; i < GPU_REG_BUF_SIZE; i++) {
for (i = 0; i < GPU_REG_BUF_SIZE; i++)
{
sGpuRegBuffer[i] = 0;
sGpuRegWaitingList[i] = EMPTY_SLOT;
}
@@ -33,20 +35,25 @@ void InitGpuRegManager()
static void CopyBufferedValueToGpuReg(u8 regOffset)
{
if (regOffset == REG_OFFSET_DISPSTAT) {
if (regOffset == REG_OFFSET_DISPSTAT)
{
REG_DISPSTAT &= ~(DISPSTAT_HBLANK_INTR | DISPSTAT_VBLANK_INTR);
REG_DISPSTAT |= GPU_REG_BUF(REG_OFFSET_DISPSTAT);
} else {
}
else
{
GPU_REG(regOffset) = GPU_REG_BUF(regOffset);
}
}
void CopyBufferedValuesToGpuRegs()
void CopyBufferedValuesToGpuRegs(void)
{
if (!sGpuRegBufferLocked) {
if (!sGpuRegBufferLocked)
{
s32 i;
for (i = 0; i < GPU_REG_BUF_SIZE; i++) {
for (i = 0; i < GPU_REG_BUF_SIZE; i++)
{
u8 regOffset = sGpuRegWaitingList[i];
if (regOffset == EMPTY_SLOT)
return;
@@ -135,7 +142,7 @@ void ClearGpuRegBits(u8 regOffset, u16 mask)
SetGpuReg(regOffset, regValue & ~mask);
}
static void SyncRegIE()
static void SyncRegIE(void)
{
if (sShouldSyncRegIE) {
u16 temp = REG_IME;

1436
src/metatile_behavior.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,77 @@
#include "global.h"
#include "money.h"
#include "event_data.h"
#include "string_util.h"
#include "text.h"
#include "menu.h"
#include "window.h"
#include "sprite.h"
#include "decompress.h"
extern const u8 gText_PokedollarVar1[];
extern const u8 gMenuMoneyGfx[];
extern const u8 gMenuMoneyPal[];
#define MAX_MONEY 999999
EWRAM_DATA static u8 sMoneyBoxWindowId = 0;
EWRAM_DATA static u8 sMoneyLabelSpriteId = 0;
#define MONEY_LABEL_TAG 0x2722
static const struct OamData sOamData_MoneyLabel =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 1,
.x = 0,
.matrixNum = 0,
.size = 2,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_MoneyLabel[] =
{
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_MoneyLabel[] =
{
sSpriteAnim_MoneyLabel,
};
static const struct SpriteTemplate sSpriteTemplate_MoneyLabel =
{
.tileTag = MONEY_LABEL_TAG,
.paletteTag = MONEY_LABEL_TAG,
.oam = &sOamData_MoneyLabel,
.anims = sSpriteAnimTable_MoneyLabel,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
static const struct CompressedSpriteSheet sSpriteSheet_MoneyLabel =
{
.data = gMenuMoneyGfx,
.size = 256,
.tag = MONEY_LABEL_TAG,
};
static const struct CompressedSpritePalette sSpritePalette_MoneyLabel =
{
.data = gMenuMoneyPal,
.tag = MONEY_LABEL_TAG
};
u32 GetMoney(u32* moneyPtr)
{
return *moneyPtr ^ gSaveBlock2Ptr->encryptionKey;
@@ -53,3 +122,79 @@ void SubtractMoney(u32* moneyPtr, u32 toSub)
SetMoney(moneyPtr, toSet);
}
bool8 IsEnoughForCostInVar0x8005(void)
{
return IsEnoughMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
}
void SubtractMoneyFromVar0x8005(void)
{
SubtractMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
}
void PrintMoneyAmountInMoneyBox(u8 windowId, int amount, u8 speed)
{
PrintMoneyAmount(windowId, 0x26, 1, amount, speed);
}
void PrintMoneyAmount(u8 windowId, u8 x, u8 y, int amount, u8 speed)
{
u8 *txtPtr;
s32 strLength;
ConvertIntToDecimalStringN(gStringVar1, amount, STR_CONV_MODE_LEFT_ALIGN, 6);
strLength = 6 - StringLength(gStringVar1);
txtPtr = gStringVar4;
while (strLength-- > 0)
*(txtPtr++) = 0x77;
StringExpandPlaceholders(txtPtr, gText_PokedollarVar1);
PrintTextOnWindow(windowId, 1, gStringVar4, x, y, speed, NULL);
}
void PrintMoneyAmountInMoneyBoxWithBorder(u8 windowId, u16 tileStart, u8 pallete, int amount)
{
SetWindowBorderStyle(windowId, FALSE, tileStart, pallete);
PrintMoneyAmountInMoneyBox(windowId, amount, 0);
}
void ChangeAmountInMoneyBox(int amount)
{
PrintMoneyAmountInMoneyBox(sMoneyBoxWindowId, amount, 0);
}
void DrawMoneyBox(int amount, u8 x, u8 y)
{
struct WindowTemplate template;
SetWindowTemplateFields(&template, 0, x + 1, y + 1, 10, 2, 15, 8);
sMoneyBoxWindowId = AddWindow(&template);
FillWindowPixelBuffer(sMoneyBoxWindowId, 0);
PutWindowTilemap(sMoneyBoxWindowId);
CopyWindowToVram(sMoneyBoxWindowId, 1);
PrintMoneyAmountInMoneyBoxWithBorder(sMoneyBoxWindowId, 0x214, 14, amount);
AddMoneyLabelObject((8 * x) + 19, (8 * y) + 11);
}
void HideMoneyBox(void)
{
RemoveMoneyLabelObject();
sub_8198070(sMoneyBoxWindowId, FALSE);
CopyWindowToVram(sMoneyBoxWindowId, 2);
RemoveWindow(sMoneyBoxWindowId);
}
void AddMoneyLabelObject(u16 x, u16 y)
{
LoadCompressedObjectPic(&sSpriteSheet_MoneyLabel);
LoadCompressedObjectPalette(&sSpritePalette_MoneyLabel);
sMoneyLabelSpriteId = CreateSprite(&sSpriteTemplate_MoneyLabel, x, y, 0);
}
void RemoveMoneyLabelObject(void)
{
DestroySpriteAndFreeResources(&gSprites[sMoneyLabelSpriteId]);
}

View File

@@ -18,6 +18,7 @@
#include "event_data.h"
#include "money.h"
#include "coins.h"
#include "text.h"
extern u8 gPlayerPartyCount;
extern u8 gDifferentSaveFile;
@@ -104,7 +105,10 @@ void ClearPokedexFlags(void)
memset(&gSaveBlock2Ptr->pokedex.seen, 0, sizeof(gSaveBlock2Ptr->pokedex.seen));
}
extern const struct ContestWinner gContestWinnerPicDummy;
const struct ContestWinner gContestWinnerPicDummy = {
.monName = _(""),
.trainerName = _("")
};
void ClearAllContestWinnerPics(void)
{

View File

@@ -35,7 +35,7 @@ extern const u8 gText_BadEgg[];
extern const u8 gText_EggNickname[];
extern u8 GetBankSide(u8 bank);
extern u8 GetBankByPlayerAI(u8 bank);
extern u8 GetBankByIdentity(u8 bank);
extern u8 GetBankIdentity(u8 bank);
u8 CountAliveMonsInBattle(u8 caseId)
@@ -90,7 +90,7 @@ u8 sub_8069F34(u8 bank)
status ^= 1;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
return GetBankByPlayerAI(status);
return GetBankByIdentity(status);
if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1)
{
u8 val;
@@ -99,14 +99,14 @@ u8 sub_8069F34(u8 bank)
val = status ^ 2;
else
val = status;
return GetBankByPlayerAI(val);
return GetBankByIdentity(val);
}
else
{
if ((gAbsentBankFlags & gBitTable[status]))
return GetBankByPlayerAI(status ^ 2);
return GetBankByIdentity(status ^ 2);
else
return GetBankByPlayerAI(status);
return GetBankByIdentity(status);
}
}
@@ -1308,10 +1308,9 @@ void sub_805EF84(u8 bank, bool8);
extern struct BattlePokemon gBattleMons[4];
/*
void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
{
u16* hpSwitchout;
s32 i;
u8 nickname[POKEMON_NAME_LENGTH * 2];
@@ -1352,15 +1351,9 @@ void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
StringCopy10(gBattleMons[bank].nickname, nickname);
GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[bank].otName);
// ewram memes from Ruby return
#ifdef NONMATCHING
gBattleStruct->hpOnSwitchout[GetBankSide(bank)] = gBattleMons[bank].hp;
#else
{
u32 side = GetBankSide(bank);
*(u16*)((void*)(gBattleStruct) + side) = gBattleMons[bank].hp;
}
#endif // NONMATCHING
hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBankSide(bank)];
*hpSwitchout = gBattleMons[bank].hp;
for (i = 0; i < 8; i++)
gBattleMons[bank].statStages[i] = 6;
@@ -1369,4 +1362,3 @@ void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
sub_803FA70(bank);
sub_805EF84(bank, FALSE);
}
*/

View File

@@ -216,7 +216,7 @@ void sub_806CF24(s32 stat)
gBankTarget = gBankInMenu;
StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]);
StringCopy(gBattleTextBuff2, gText_StatRose);
StrCpyDecodeToDisplayedStringBattle(gText_PkmnsStatChanged2);
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
}
u8 *sub_806CF78(u16 itemId)
@@ -251,7 +251,7 @@ u8 *sub_806CF78(u16 itemId)
else
{
gBankAttacker = gBankInMenu;
StrCpyDecodeToDisplayedStringBattle(gText_PkmnGettingPumped);
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
}
}
}
@@ -259,7 +259,7 @@ u8 *sub_806CF78(u16 itemId)
if (itemEffect[3] & 0x80)
{
gBankAttacker = gBankInMenu;
StrCpyDecodeToDisplayedStringBattle(gText_PkmnShroudedInMist);
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
}
return gDisplayedStringBattle;
@@ -601,9 +601,9 @@ bool8 sub_806D7EC(void)
return retVal;
}
bool8 sub_806D82C(u8 id)
bool16 sub_806D82C(u8 id)
{
bool8 retVal = FALSE;
bool16 retVal = FALSE;
switch (gLinkPlayers[id].lp_field_18)
{
case 0:
@@ -1361,20 +1361,20 @@ void BoxMonRestorePP(struct BoxPokemon *boxMon)
void sub_806E994(void)
{
gLastUsedAbility = gBattleStruct->field_B0;
gBattleTextBuff1[0] = 0xFD;
gBattleTextBuff1[1] = 4;
gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
gBattleTextBuff1[2] = gBattleStruct->field_49;
gBattleTextBuff1[4] = EOS;
gBattleTextBuff1[4] = B_BUFF_EOS;
if (!GetBankSide(gBattleStruct->field_49))
gBattleTextBuff1[3] = pokemon_order_func(gBattlePartyID[gBattleStruct->field_49]);
else
gBattleTextBuff1[3] = gBattlePartyID[gBattleStruct->field_49];
gBattleTextBuff2[0] = 0xFD;
gBattleTextBuff2[1] = 4;
gBattleTextBuff2[2] = gBankInMenu;
gBattleTextBuff2[3] = pokemon_order_func(gBattlePartyID[gBankInMenu]);
gBattleTextBuff2[4] = EOS;
StrCpyDecodeBattle(gText_PkmnsXPreventsSwitching, gStringVar4);
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBankInMenu, pokemon_order_func(gBattlePartyID[gBankInMenu]))
BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
}
struct PokeItem
@@ -1388,7 +1388,7 @@ extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
static s32 GetWildMonTableIdInAlteringCave(u16 species)
{
s32 i;
for (i = 0; i < 9; i++)
for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++)
if (gAlteringCaveWildMonHeldItems[i].species == species)
return i;
return 0;
@@ -1511,8 +1511,6 @@ static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
}
}
void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3);
void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
{
if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))

218
src/roamer.c Normal file
View File

@@ -0,0 +1,218 @@
#include "global.h"
#include "roamer.h"
#include "pokemon.h"
#include "rng.h"
#include "species.h"
#include "event_data.h"
enum
{
MAP_GRP = 0, // map group
MAP_NUM = 1, // map number
};
EWRAM_DATA static u8 sLocationHistory[3][2] = {0};
EWRAM_DATA static u8 sRoamerLocation[2] = {0};
static const u8 sRoamerLocations[][6] =
{
{ 0x19, 0x1A, 0x20, 0x21, 0x31, 0xFF },
{ 0x1A, 0x19, 0x20, 0x21, 0xFF, 0xFF },
{ 0x20, 0x1A, 0x19, 0x21, 0xFF, 0xFF },
{ 0x21, 0x20, 0x19, 0x1A, 0x22, 0x26 },
{ 0x22, 0x21, 0x23, 0xFF, 0xFF, 0xFF },
{ 0x23, 0x22, 0x24, 0xFF, 0xFF, 0xFF },
{ 0x24, 0x23, 0x25, 0x26, 0xFF, 0xFF },
{ 0x25, 0x24, 0x26, 0xFF, 0xFF, 0xFF },
{ 0x26, 0x25, 0x21, 0xFF, 0xFF, 0xFF },
{ 0x27, 0x24, 0x28, 0x29, 0xFF, 0xFF },
{ 0x28, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
{ 0x29, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
{ 0x2A, 0x28, 0x29, 0x2B, 0xFF, 0xFF },
{ 0x2B, 0x2A, 0x2C, 0xFF, 0xFF, 0xFF },
{ 0x2C, 0x2B, 0x2D, 0xFF, 0xFF, 0xFF },
{ 0x2D, 0x2C, 0x2E, 0xFF, 0xFF, 0xFF },
{ 0x2E, 0x2D, 0x2F, 0xFF, 0xFF, 0xFF },
{ 0x2F, 0x2E, 0x30, 0xFF, 0xFF, 0xFF },
{ 0x30, 0x2F, 0x31, 0xFF, 0xFF, 0xFF },
{ 0x31, 0x30, 0x19, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
};
void ClearRoamerData(void)
{
memset(&gSaveBlock1Ptr->roamer, 0, sizeof(struct Roamer));
(&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS;
}
void ClearRoamerLocationData(void)
{
u8 i;
for (i = 0; i < 3; i++)
{
sLocationHistory[i][MAP_GRP] = 0;
sLocationHistory[i][MAP_NUM] = 0;
}
sRoamerLocation[MAP_GRP] = 0;
sRoamerLocation[MAP_NUM] = 0;
}
static void CreateInitialRoamerMon(bool16 createLatios)
{
if (!createLatios)
(&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS;
else
(&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIOS;
CreateMon(&gEnemyParty[0], (&gSaveBlock1Ptr->roamer)->species, 40, 0x20, 0, 0, 0, 0);
(&gSaveBlock1Ptr->roamer)->level = 40;
(&gSaveBlock1Ptr->roamer)->status = 0;
(&gSaveBlock1Ptr->roamer)->active = TRUE;
(&gSaveBlock1Ptr->roamer)->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS);
(&gSaveBlock1Ptr->roamer)->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY);
(&gSaveBlock1Ptr->roamer)->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP);
(&gSaveBlock1Ptr->roamer)->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL);
(&gSaveBlock1Ptr->roamer)->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY);
(&gSaveBlock1Ptr->roamer)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE);
(&gSaveBlock1Ptr->roamer)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART);
(&gSaveBlock1Ptr->roamer)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH);
sRoamerLocation[MAP_GRP] = 0;
sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % 20][0];
}
void InitRoamer(void)
{
ClearRoamerData();
ClearRoamerLocationData();
CreateInitialRoamerMon(gSpecialVar_0x8004);
}
void UpdateLocationHistoryForRoamer(void)
{
sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP];
sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM];
sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP];
sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM];
sLocationHistory[0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup;
sLocationHistory[0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum;
}
void RoamerMoveToOtherLocationSet(void)
{
u8 val = 0;
struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
if (!roamer->active)
return;
sRoamerLocation[MAP_GRP] = val;
while (1)
{
val = sRoamerLocations[Random() % 20][0];
if (sRoamerLocation[MAP_NUM] != val)
{
sRoamerLocation[MAP_NUM] = val;
return;
}
}
}
void RoamerMove(void)
{
u8 locSet = 0;
if ((Random() % 16) == 0)
{
RoamerMoveToOtherLocationSet();
}
else
{
struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
if (!roamer->active)
return;
while (locSet < 20)
{
if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0])
{
u8 mapNum;
while (1)
{
mapNum = sRoamerLocations[locSet][(Random() % 5) + 1];
if (!(sLocationHistory[2][MAP_GRP] == 0 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF)
break;
}
sRoamerLocation[MAP_NUM] = mapNum;
return;
}
locSet++;
}
}
}
bool8 IsRoamerAt(u8 mapGroup, u8 mapNum)
{
struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM])
return TRUE;
else
return FALSE;
}
void CreateRoamerMonInstance(void)
{
struct Pokemon *mon;
struct Roamer *roamer;
mon = &gEnemyParty[0];
ZeroEnemyPartyMons();
roamer = &gSaveBlock1Ptr->roamer;
CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality);
SetMonData(mon, MON_DATA_STATUS, &gSaveBlock1Ptr->roamer.status);
SetMonData(mon, MON_DATA_HP, &gSaveBlock1Ptr->roamer.hp);
SetMonData(mon, MON_DATA_COOL, &gSaveBlock1Ptr->roamer.cool);
SetMonData(mon, MON_DATA_BEAUTY, &gSaveBlock1Ptr->roamer.beauty);
SetMonData(mon, MON_DATA_CUTE, &gSaveBlock1Ptr->roamer.cute);
SetMonData(mon, MON_DATA_SMART, &gSaveBlock1Ptr->roamer.smart);
SetMonData(mon, MON_DATA_TOUGH, &gSaveBlock1Ptr->roamer.tough);
}
bool8 TryStartRoamerEncounter(void)
{
if (IsRoamerAt(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) == TRUE && (Random() % 4) == 0)
{
CreateRoamerMonInstance();
return TRUE;
}
else
{
return FALSE;
}
}
void UpdateRoamerHPStatus(struct Pokemon *mon)
{
(&gSaveBlock1Ptr->roamer)->hp = GetMonData(mon, MON_DATA_HP);
(&gSaveBlock1Ptr->roamer)->status = GetMonData(mon, MON_DATA_STATUS);
RoamerMoveToOtherLocationSet();
}
void SetRoamerInactive(void)
{
struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
roamer->active = FALSE;
}
void GetRoamerLocation(u8 *mapGroup, u8 *mapNum)
{
*mapGroup = sRoamerLocation[MAP_GRP];
*mapNum = sRoamerLocation[MAP_NUM];
}

View File

@@ -18,7 +18,7 @@ struct PokeblockFeeder
#define NUM_POKEBLOCK_FEEDERS 10
extern u8 gBattleOutcome;
extern void* gUnknown_03005DAC;
extern void* gFieldCallback;
extern u8 gUnknown_082A4B8A[];
extern u8 gUnknown_082A4B6F[];
@@ -118,7 +118,7 @@ void sub_80FC190(void)
{
ScriptContext2_RunNewScript(gUnknown_082A4B4C);
warp_in();
gUnknown_03005DAC = sub_80AF6F0;
gFieldCallback = sub_80AF6F0;
SetMainCallback2(c2_load_new_map);
}
else if (gBattleOutcome == BATTLE_CAUGHT)

View File

@@ -2,12 +2,15 @@
#include "gba/flash_internal.h"
#include "save.h"
#include "game_stat.h"
#include "task.h"
extern struct SaveSectionOffsets gSaveSectionOffsets[0xE];
extern struct SaveSectionLocation gRamSaveSectionLocations[0xE];
extern u8 gDecompressionBuffer[];
extern u32 gFlashMemoryPresent;
extern u16 gUnknown_03006294;
extern bool8 gSoftResetDisabled;
extern const struct SaveSectionOffsets gSaveSectionOffsets[0xE];
extern void DoSaveFailedScreen(u8); // save_failed_screen
extern void LoadSerializedGame(void); // load_save
@@ -576,84 +579,27 @@ u16 CalculateChecksum(void *data, u16 size)
return ((checksum >> 16) + checksum);
}
#ifdef NONMATCHING
// the initial allocation of the pointer and toAdd variable doesnt match up with the original function. however, forcing it is impossible since gRamSaveSectionLocations is loaded first.
void UpdateSaveAddresses(void)
{
int i = 0;
gRamSaveSectionLocations[i].data = gSaveBlock2Ptr + gSaveSectionOffsets[0].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[0].size;
for(i = 1; i < 5; i++)
gRamSaveSectionLocations[i].data = (void*)(gSaveBlock2Ptr) + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
for (i = 1; i < 5; i++)
{
gRamSaveSectionLocations[i].data = gSaveBlock1Ptr + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].data = (void*)(gSaveBlock1Ptr) + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
}
for(i = 5; i < 14; i++)
for (i = 5; i < 14; i++)
{
gRamSaveSectionLocations[i].data = gPokemonStoragePtr + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].data = (void*)(gPokemonStoragePtr) + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
i++;i--; // needed to match
}
}
#else
__attribute__((naked))
void UpdateSaveAddresses(void)
{
asm(".syntax unified\n\
push {r4,r5,lr}\n\
ldr r3, =gRamSaveSectionLocations\n\
ldr r0, =gSaveBlock2Ptr\n\
ldr r2, =gSaveSectionOffsets\n\
ldrh r1, [r2]\n\
ldr r0, [r0]\n\
adds r0, r1\n\
str r0, [r3]\n\
ldrh r0, [r2, 0x2]\n\
strh r0, [r3, 0x4]\n\
ldr r5, =gSaveBlock1Ptr\n\
adds r3, 0x8\n\
adds r2, 0x4\n\
movs r4, 0x3\n\
_081531AC:\n\
ldrh r0, [r2]\n\
ldr r1, [r5]\n\
adds r1, r0\n\
str r1, [r3]\n\
ldrh r0, [r2, 0x2]\n\
strh r0, [r3, 0x4]\n\
adds r3, 0x8\n\
adds r2, 0x4\n\
subs r4, 0x1\n\
cmp r4, 0\n\
bge _081531AC\n\
movs r4, 0x5\n\
ldr r1, =gRamSaveSectionLocations\n\
ldr r5, =gPokemonStoragePtr\n\
ldr r0, =gSaveSectionOffsets\n\
adds r3, r1, 0\n\
adds r3, 0x28\n\
adds r2, r0, 0\n\
adds r2, 0x14\n\
_081531D2:\n\
ldrh r0, [r2]\n\
ldr r1, [r5]\n\
adds r1, r0\n\
str r1, [r3]\n\
ldrh r0, [r2, 0x2]\n\
strh r0, [r3, 0x4]\n\
adds r3, 0x8\n\
adds r2, 0x4\n\
adds r4, 0x1\n\
cmp r4, 0xD\n\
ble _081531D2\n\
pop {r4,r5}\n\
pop {r0}\n\
bx r0\n\
.pool\n\
.syntax divided");
}
#endif
extern u32 GetGameStat(u8 index); // rom4
extern void IncrementGameStat(u8 index); // rom4
@@ -894,3 +840,85 @@ u32 sub_8153634(u8 sector, u8* src)
return 0xFF;
return 1;
}
extern void save_serialize_map(void);
extern void sub_8076D5C(void);
extern void sav2_gender2_inplace_and_xFE(void);
extern void sub_800ADF8(void);
extern bool8 sub_800A520(void);
void sub_8153688(u8 taskId)
{
s16* taskData = gTasks[taskId].data;
switch (taskData[0])
{
case 0:
gSoftResetDisabled = TRUE;
taskData[0] = 1;
break;
case 1:
sub_800ADF8();
taskData[0] = 2;
break;
case 2:
if (sub_800A520())
{
if (taskData[2] == 0)
save_serialize_map();
taskData[0] = 3;
}
break;
case 3:
if (taskData[2] == 0)
sub_8076D5C();
sub_8153380();
taskData[0] = 4;
break;
case 4:
if (++taskData[1] == 5)
{
taskData[1] = 0;
taskData[0] = 5;
}
break;
case 5:
if (sub_81533AC())
taskData[0] = 6;
else
taskData[0] = 4;
break;
case 6:
sub_81533E0();
taskData[0] = 7;
break;
case 7:
if (taskData[2] == 0)
sav2_gender2_inplace_and_xFE();
sub_800ADF8();
taskData[0] = 8;
break;
case 8:
if (sub_800A520())
{
sub_8153408();
taskData[0] = 9;
}
break;
case 9:
sub_800ADF8();
taskData[0] = 10;
break;
case 10:
if (sub_800A520())
taskData[0]++;
break;
case 11:
if (++taskData[1] > 5)
{
gSoftResetDisabled = FALSE;
DestroyTask(taskId);
}
break;
}
}

View File

@@ -240,12 +240,11 @@ void RunTextPrinters(void)
}
}
bool8 IsTextPrinterActive(u8 id)
bool16 IsTextPrinterActive(u8 id)
{
return gTextPrinters[id].sub_union.sub.active;
}
u32 RenderFont(struct TextPrinter *textPrinter)
{
u32 ret;

View File

@@ -1,12 +1,6 @@
#include "global.h"
#include "trig.h"
// Converts a number to Q8.8 fixed-point format
#define Q_8_8(n) ((s16)((n) * 256))
// Converts a number to Q4.12 fixed-point format
#define Q_4_12(n) ((s16)((n) * 4096))
// Values of sin(x*(π/128)) as Q8.8 fixed-point numbers from x = 0 to x = 319
const s16 gSineTable[] =
{

View File

@@ -451,7 +451,7 @@ void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16
FillBitmapRect4Bit(&pixelRect, x, y, width, height, fillValue);
}
void CopyToWindowPixelBuffer(u8 windowId, u8 *src, u16 size, u16 tileOffset)
void CopyToWindowPixelBuffer(u8 windowId, const u8 *src, u16 size, u16 tileOffset)
{
if (size != 0)
CpuCopy16(src, gWindows[windowId].tileData + (0x20 * tileOffset), size);