From 2adbacf43bae125bb3fcaed647cf01344ecb9662 Mon Sep 17 00:00:00 2001 From: Philippe Symons Date: Tue, 23 Jul 2024 23:40:19 +0200 Subject: [PATCH] Avoid performance hit in Gen1PlayerPokemonStorage Make it possible for Gen1PlayerPokemonStorages' Gen1Party and Gen1Box to avoid the performance hit in ::getPokemon caused by the recalculation of the pokemons' level. This recalculation would read the pokemon stats datastructure, which could be slow on the N64 transfer pak. --- include/gen1/Gen1PlayerPokemonStorage.h | 4 ++-- src/gen1/Gen1PlayerPokemonStorage.cpp | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/gen1/Gen1PlayerPokemonStorage.h b/include/gen1/Gen1PlayerPokemonStorage.h index 36f8fc5..fb81990 100644 --- a/include/gen1/Gen1PlayerPokemonStorage.h +++ b/include/gen1/Gen1PlayerPokemonStorage.h @@ -24,7 +24,7 @@ public: /** * Reads the pokemon data structure at the specified partyIndex */ - bool getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPokemon); + bool getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPokemon, bool shouldRecalculateLevel = true); /** * Overwrites the pokemon data structure at the specified partyIndex */ @@ -56,7 +56,7 @@ public: * Gets the pokemon species index at the given index within the box */ uint8_t getSpeciesAtIndex(uint8_t index); - bool getPokemon(uint8_t index, Gen1TrainerPokemon& outTrainerPokemon); + bool getPokemon(uint8_t index, Gen1TrainerPokemon& outTrainerPokemon, bool shouldRecalculateLevel = true); bool setPokemon(uint8_t index, Gen1TrainerPokemon& poke); uint8_t getNumberOfPokemon(); uint8_t getMaxNumberOfPokemon(); diff --git a/src/gen1/Gen1PlayerPokemonStorage.cpp b/src/gen1/Gen1PlayerPokemonStorage.cpp index d083f04..8f49e0a 100644 --- a/src/gen1/Gen1PlayerPokemonStorage.cpp +++ b/src/gen1/Gen1PlayerPokemonStorage.cpp @@ -210,7 +210,7 @@ uint8_t Gen1Party::getSpeciesAtIndex(uint8_t partyIndex) return partyMeta.species_index_list[partyIndex]; } -bool Gen1Party::getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPokemon) +bool Gen1Party::getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPokemon, bool shouldRecalculateLevel) { Gen1PokeStats stats; const uint8_t PARTY_POKEMON_NUM_BYTES = 44; @@ -221,7 +221,7 @@ bool Gen1Party::getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPok readCommonPokeData(saveManager_, outTrainerPokemon); // according to https://bulbapedia.bulbagarden.net/wiki/Pok%C3%A9mon_data_structure_(Generation_I) - // the level is stored a second time here for some reason. Ignore it. + // the level is stored a second time here for some reason. saveManager_.advance(); saveManager_.readUint16(outTrainerPokemon.max_hp, Endianness::BIG); @@ -231,8 +231,13 @@ bool Gen1Party::getPokemon(uint8_t partyIndex, Gen1TrainerPokemon& outTrainerPok saveManager_.readUint16(outTrainerPokemon.special, Endianness::BIG); // the level field above is kinda unreliable. the only reliable way is to base it on the exp field - gameReader_.readPokemonStatsForIndex(outTrainerPokemon.poke_index, stats); - outTrainerPokemon.level = getLevelForExp(outTrainerPokemon.exp, stats.growth_rate); + // doing the recalculation causes a performance hit though, because the stats data is being read. + // shouldRecalculateLevel == false lets you avoid this. + if(shouldRecalculateLevel) + { + gameReader_.readPokemonStatsForIndex(outTrainerPokemon.poke_index, stats); + outTrainerPokemon.level = getLevelForExp(outTrainerPokemon.exp, stats.growth_rate); + } return true; } @@ -408,7 +413,7 @@ uint8_t Gen1Box::getSpeciesAtIndex(uint8_t index) return boxMeta.species_index_list[index]; } -bool Gen1Box::getPokemon(uint8_t index, Gen1TrainerPokemon& outTrainerPokemon) +bool Gen1Box::getPokemon(uint8_t index, Gen1TrainerPokemon& outTrainerPokemon, bool shouldRecalculateLevel) { Gen1PokeStats stats; const uint8_t BOX_POKEMON_NUM_BYTES = 33; @@ -423,8 +428,13 @@ bool Gen1Box::getPokemon(uint8_t index, Gen1TrainerPokemon& outTrainerPokemon) readCommonPokeData(saveManager_, outTrainerPokemon); // the level field above is kinda unreliable. the only reliable way is to base it on the exp field - gameReader_.readPokemonStatsForIndex(outTrainerPokemon.poke_index, stats); - outTrainerPokemon.level = getLevelForExp(outTrainerPokemon.exp, stats.growth_rate); + // doing the recalculation causes a performance hit though, because the stats data is being read. + // shouldRecalculateLevel == false lets you avoid this. + if(shouldRecalculateLevel) + { + gameReader_.readPokemonStatsForIndex(outTrainerPokemon.poke_index, stats); + outTrainerPokemon.level = getLevelForExp(outTrainerPokemon.exp, stats.growth_rate); + } return true; }