Fix bug: Japanese saves were not detected correctly for gen I

This commit is contained in:
Philippe Symons 2024-12-12 13:22:31 +01:00
parent 3d86aa80f5
commit 99b2e41f42
4 changed files with 67 additions and 33 deletions

View File

@ -22,7 +22,7 @@
* Yes, I'm aware this is a bit unclean, but once the relevant rom offsets are found once, you don't typically need this tool anymore.
* Still, I'm leaving this application in the codebase in case I need more rom offsets later (or in case Korean localization support would get implemented at some point)
*/
static const Gen1LocalizationLanguage g1_localization = Gen1LocalizationLanguage::ENGLISH;
static const Gen1LocalizationLanguage g1_localization = Gen1LocalizationLanguage::JAPANESE;
static const Gen2LocalizationLanguage g2_localization = Gen2LocalizationLanguage::ENGLISH;
static uint32_t findBinaryPattern(uint8_t* buffer, size_t bufferSize, uint8_t* pattern, size_t patternSize)
@ -138,7 +138,7 @@ static void processGen1(Gen1GameType gameType, uint8_t* romBuffer, uint8_t* loca
findBinaryPattern(localizedRomBuffer, localizedRomBufferSize, romBuffer + eng.numbers, 11);
// WARNING: Modify this variable with the localized name of the pokémon we're trying to look up. (RHYDON, because it's index 1)
const char* pokeNames[] = {"RHYDON"};
const char* pokeNames[] = {"サイドン"};
printf("Names: 0x%08x\n", findNames(localizedRomBuffer, localizedRomBufferSize, pokeNames, 1, 1));
printf("IconTypes:\n");
findBinaryPattern(localizedRomBuffer, localizedRomBufferSize, romBuffer + eng.iconTypes, 11);

View File

@ -10,11 +10,11 @@
/**
* @brief This function calculates the main data checksum
*/
uint8_t calculateMainDataChecksum(ISaveManager& saveManager)
uint8_t calculateMainDataChecksum(ISaveManager& saveManager, uint8_t localization)
{
Gen1Checksum checksum;
const uint16_t checksummedDataStart = 0x598;
const uint16_t checksummedDataEnd = 0x1523;
const uint16_t checksummedDataEnd = (localization != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x1523: 0x1594;
const uint16_t numBytes = checksummedDataEnd - checksummedDataStart;
uint16_t i;
uint8_t byte;
@ -322,7 +322,9 @@ const char *Gen1GameReader::getRivalName() const
{
static char result[20];
uint8_t encodedRivalName[0xB];
saveManager_.seek(0x25F6);
const uint16_t savOffset = (localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x25F6 : 0x25F1;
saveManager_.seek(savOffset);
saveManager_.readUntil(encodedRivalName, 0x50, sizeof(encodedRivalName));
gen1_decodePokeText(encodedRivalName, sizeof(encodedRivalName), result, sizeof(result), (Gen1LocalizationLanguage)localization_);
@ -332,8 +334,8 @@ const char *Gen1GameReader::getRivalName() const
uint16_t Gen1GameReader::getTrainerID() const
{
uint16_t result;
saveManager_.seek(0x2605);
const uint16_t savOffset = (localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x2605 : 0x25FB;
saveManager_.seek(savOffset);
saveManager_.readUint16(result);
return result;
@ -352,8 +354,9 @@ Gen1Box Gen1GameReader::getBox(uint8_t boxIndex)
uint8_t Gen1GameReader::getCurrentBoxIndex()
{
uint8_t byte;
const uint16_t savOffset = (localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x284C : 0x2842;
saveManager_.seek(0x284C);
saveManager_.seek(savOffset);
saveManager_.readByte(byte);
return byte & 0x3F;
@ -361,8 +364,18 @@ uint8_t Gen1GameReader::getCurrentBoxIndex()
bool Gen1GameReader::getPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const
{
const uint16_t saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
uint16_t saveOffset;
uint8_t byte;
if(localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE)
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
}
else
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B1 : 0x259E;
}
if(pokedexNumber < 1 || pokedexNumber > 151)
{
return false;
@ -380,8 +393,18 @@ bool Gen1GameReader::getPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber)
void Gen1GameReader::setPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber) const
{
const uint16_t saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
uint16_t saveOffset;
uint8_t byte;
if(localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE)
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
}
else
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B1 : 0x259E;
}
if(pokedexNumber < 1 || pokedexNumber > 151)
{
return;
@ -400,10 +423,19 @@ void Gen1GameReader::setPokedexFlag(PokedexFlag dexFlag, uint8_t pokedexNumber)
uint8_t Gen1GameReader::getPokedexCounter(PokedexFlag dexFlag) const
{
const uint16_t saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
uint16_t saveOffset;
uint8_t bytes[19];
uint8_t result = 0;
if(localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE)
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B6 : 0x25A3;
}
else
{
saveOffset = (dexFlag == POKEDEX_SEEN) ? 0x25B1 : 0x259E;
}
saveManager_.seek(saveOffset);
saveManager_.read(bytes, sizeof(bytes));
@ -500,22 +532,22 @@ uint8_t Gen1GameReader::addDistributionPokemon(const Gen1DistributionPokemon& di
bool Gen1GameReader::isMainChecksumValid()
{
const uint16_t mainDataChecksumOffset = 0x3523;
const uint16_t mainDataChecksumOffset = (localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x3523 : 0x3594;
uint8_t storedChecksum;
uint8_t calculatedChecksum;
saveManager_.seek(mainDataChecksumOffset);
saveManager_.readByte(storedChecksum);
calculatedChecksum = calculateMainDataChecksum(saveManager_);
calculatedChecksum = calculateMainDataChecksum(saveManager_, localization_);
return (storedChecksum == calculatedChecksum);
}
void Gen1GameReader::updateMainChecksum()
{
const uint16_t mainDataChecksumOffset = 0x3523;
const uint8_t calculatedChecksum = calculateMainDataChecksum(saveManager_);
const uint16_t mainDataChecksumOffset = (localization_ != (uint8_t)Gen1LocalizationLanguage::JAPANESE) ? 0x3523 : 0x3594;
const uint8_t calculatedChecksum = calculateMainDataChecksum(saveManager_, localization_);
saveManager_.seek(mainDataChecksumOffset);
saveManager_.writeByte(calculatedChecksum);

View File

@ -58,14 +58,14 @@ static const Gen1LocalizationRomOffsets g1_localizationOffsetsRB[] = {
},
// Japanese
{
.stats = 0x383DE,
.statsMew = 0x425B,
.numbers = 0x42784,
.names = 0x39446,
.iconTypes = 0x71DC1,
.icons = 0x71C74,
.paletteIndices = 0x72A0E,
.palettes = 0x72AA5
.stats = 0x38000,
.statsMew = 0x4200,
.numbers = 0x4279A,
.names = 0x39068,
.iconTypes = 0x71DD1,
.icons = 0x71C84,
.paletteIndices = 0x72A1F,
.palettes = 0x72AB6
}
};

View File

@ -25,18 +25,20 @@ static const uint8_t OT_NAME_SIZE = 0xB;
* @brief This function will load the metadata of the trainer party into the specified outPartyMeta variable.
* Note that it won't contain the detailed data about the pokemon in the party.
*/
static bool getPartyMetadata(ISaveManager& saveManager, Gen1TrainerPartyMeta &outPartyMeta)
static bool getPartyMetadata(ISaveManager& saveManager, Gen1TrainerPartyMeta &outPartyMeta, Gen1LocalizationLanguage localization)
{
saveManager.seek(0x2F2C);
const uint16_t savOffset = (localization != Gen1LocalizationLanguage::JAPANESE) ? 0x2F2C : 0x2ED5;
saveManager.seek(savOffset);
saveManager.readByte(outPartyMeta.number_of_pokemon);
saveManager.read(outPartyMeta.species_index_list, 6);
outPartyMeta.species_index_list[6] = 0xFF;
return true;
}
static void writePartyMetadata(ISaveManager& saveManager, Gen1TrainerPartyMeta& partyMeta)
static void writePartyMetadata(ISaveManager& saveManager, Gen1TrainerPartyMeta& partyMeta, Gen1LocalizationLanguage localization)
{
saveManager.seek(0x2F2C);
const uint16_t savOffset = (localization != Gen1LocalizationLanguage::JAPANESE) ? 0x2F2C : 0x2ED5;
saveManager.seek(savOffset);
saveManager.writeByte(partyMeta.number_of_pokemon);
saveManager.write(partyMeta.species_index_list, 6);
saveManager.writeByte(0xFF);
@ -202,7 +204,7 @@ Gen1Party::~Gen1Party()
uint8_t Gen1Party::getSpeciesAtIndex(uint8_t partyIndex)
{
Gen1TrainerPartyMeta partyMeta;
getPartyMetadata(saveManager_, partyMeta);
getPartyMetadata(saveManager_, partyMeta, localization_);
if(partyIndex >= partyMeta.number_of_pokemon)
{
@ -247,7 +249,7 @@ bool Gen1Party::setPokemon(uint8_t partyIndex, Gen1TrainerPokemon& poke)
const uint8_t PARTY_POKEMON_NUM_BYTES = 44;
const uint8_t FIRST_POKE_STRUCT_OFFSET = 8;
Gen1TrainerPartyMeta partyMeta;
getPartyMetadata(saveManager_, partyMeta);
getPartyMetadata(saveManager_, partyMeta, localization_);
if(partyIndex >= partyMeta.number_of_pokemon)
{
@ -263,7 +265,7 @@ bool Gen1Party::setPokemon(uint8_t partyIndex, Gen1TrainerPokemon& poke)
partyMeta.species_index_list[partyMeta.number_of_pokemon] = 0xFF;
}
writePartyMetadata(saveManager_, partyMeta);
writePartyMetadata(saveManager_, partyMeta, localization_);
// make sure the stat fields are filled in by recalculating them.
// this is the same as what happens when withdrawing them from an ingame PC box
@ -289,7 +291,7 @@ bool Gen1Party::setPokemon(uint8_t partyIndex, Gen1TrainerPokemon& poke)
uint8_t Gen1Party::getNumberOfPokemon()
{
Gen1TrainerPartyMeta partyMeta;
if(!getPartyMetadata(saveManager_, partyMeta))
if(!getPartyMetadata(saveManager_, partyMeta, localization_))
{
return 0;
}
@ -360,7 +362,7 @@ void Gen1Party::setOriginalTrainerOfPokemon(uint8_t partyIndex, const char* orig
bool Gen1Party::add(Gen1TrainerPokemon& poke, const char* originalTrainerID, const char* nickname)
{
Gen1TrainerPartyMeta partyMeta;
getPartyMetadata(saveManager_, partyMeta);
getPartyMetadata(saveManager_, partyMeta, localization_);
const uint8_t partyIndex = partyMeta.number_of_pokemon;
if(partyIndex >= getMaxNumberOfPokemon())
@ -376,7 +378,7 @@ bool Gen1Party::add(Gen1TrainerPokemon& poke, const char* originalTrainerID, con
partyMeta.species_index_list[partyMeta.number_of_pokemon] = 0xFF;
}
writePartyMetadata(saveManager_, partyMeta);
writePartyMetadata(saveManager_, partyMeta, localization_);
if(!setPokemon(partyIndex, poke))
{
return false;