Add gen1_determineGameLanguage() and use it automatically in Gen1GameReader if not specified in the constructor

This commit is contained in:
Philippe Symons 2024-11-15 12:34:33 +01:00
parent 3065163b1b
commit 0f56da84b6
6 changed files with 58 additions and 5 deletions

View File

@ -11,11 +11,9 @@
using OutputFormat = SpriteRenderer::OutputFormat;
static const LocalizationLanguage g_localization = LocalizationLanguage::ENGLISH;
static void decodeGen1Icon(IRomReader& romReader, ISaveManager& saveManager, Gen1GameType gen1Type, Gen1PokemonIconType iconType, bool firstFrame)
{
Gen1GameReader gameReader(romReader, saveManager, gen1Type, g_localization);
Gen1GameReader gameReader(romReader, saveManager, gen1Type);
SpriteRenderer renderer;
char fileNameBuf[100];
uint8_t* spriteBuffer;

View File

@ -68,6 +68,23 @@ static uint32_t findNames(uint8_t* buffer, size_t bufferSize, const char** nameL
return 0xFFFFFFFF;
}
#if 0
static void dumpHex(const uint8_t* buffer, uint16_t numBytes, const char* prefix)
{
uint16_t i = 0;
while(i < numBytes)
{
if(i % 8 == 0)
{
printf("\n%s", prefix);
}
printf("%02hhX ", buffer[i]);
++i;
}
printf("\n");
}
#endif
int main(int argc, char** argv)
{
if(argc != 3)
@ -127,7 +144,7 @@ int main(int argc, char** argv)
findBinaryPattern(localizedRomBuffer, localizedRomBufferSize, romBuffer + eng->statsMew, 11);
printf("Numbers:\n");
findBinaryPattern(localizedRomBuffer, localizedRomBufferSize, romBuffer + eng->numbers, 11);
const char* pokeNames[] = {"サイドン"};
const char* pokeNames[] = {"RHYDON"};
printf("Names: 0x%08x\n", findNames(localizedRomBuffer, localizedRomBufferSize, pokeNames, 1));
printf("IconTypes:\n");
findBinaryPattern(localizedRomBuffer, localizedRomBufferSize, romBuffer + eng->iconTypes, 11);

View File

@ -5,6 +5,7 @@
#include "Gen1Localization.h"
class Gen1GameReader;
class IRomReader;
typedef struct Gen1DistributionPokemon Gen1DistributionPokemon;
enum class Gen1GameType
@ -124,6 +125,11 @@ private:
*/
Gen1GameType gen1_determineGameType(const GameboyCartridgeHeader& cartridgeHeader);
/**
* @brief this function determines the games' language
*/
LocalizationLanguage gen1_determineGameLanguage(IRomReader& romReader, Gen1GameType gameType);
void gen1_recalculatePokeStats(Gen1GameReader& gameReader, Gen1TrainerPokemon& poke);
/**

View File

@ -13,7 +13,7 @@ class ISaveManager;
class Gen1GameReader
{
public:
Gen1GameReader(IRomReader& romReader, ISaveManager& saveManager, Gen1GameType gameType, LocalizationLanguage language = LocalizationLanguage::ENGLISH);
Gen1GameReader(IRomReader& romReader, ISaveManager& saveManager, Gen1GameType gameType, LocalizationLanguage language = LocalizationLanguage::MAX);
/**
* @brief get the name of a pokémon based on an index number

View File

@ -1,5 +1,6 @@
#include "gen1/Gen1Common.h"
#include "gen1/Gen1GameReader.h"
#include "RomReader.h"
#include "utils.h"
#include "common.h"
@ -10,6 +11,10 @@
#define POKEMON_RED_CARTRIDGE_TITLE "POKEMON RED"
#define POKEMON_YELLOW_CARTRIDGE_TITLE "POKEMON YELLOW"
static const uint8_t g1_indexNumberMapFingerprint[] = {
0x70, 0x73, 0x20, 0x23, 0x15, 0x64, 0x22, 0x50,
0x02, 0x67, 0x6C, 0x66, 0x58, 0x5E, 0x1D, 0x1F,
};
static const TextCodePair gen1TextCodesMain[] = {
{0x4F, " "},
@ -379,6 +384,29 @@ Gen1GameType gen1_determineGameType(const GameboyCartridgeHeader& cartridgeHeade
return result;
}
LocalizationLanguage gen1_determineGameLanguage(IRomReader& romReader, Gen1GameType gameType)
{
// The pokemon index-to-pokedex-number map has a unique rom offset in each of the game localizations.
// It also should have the exact same data in all gen 1 games and all of their localizations.
// Therefore we can use a fingerprint byte pattern to check these locations to figure out which localization we have.
const Gen1LocalizationRomOffsets* romOffsetList = (gameType != Gen1GameType::YELLOW) ? g1_localizationOffsetsRB : g1_localizationOffsetsY;
uint8_t buffer[sizeof(g1_indexNumberMapFingerprint)];
for(uint8_t i=0; i < static_cast<uint8_t>(LocalizationLanguage::MAX); ++i)
{
romReader.seek(romOffsetList[i].numbers);
romReader.read(buffer, sizeof(g1_indexNumberMapFingerprint));
if(memcmp(buffer, g1_indexNumberMapFingerprint, sizeof(g1_indexNumberMapFingerprint)) == 0)
{
// we found the fingerprint at the "numbers" offset of the current localization!
// Therefore we know which game language we're dealing with!
return (LocalizationLanguage)i;
}
}
return LocalizationLanguage::MAX;
}
void gen1_recalculatePokeStats(Gen1GameReader& reader, Gen1TrainerPokemon& poke)
{
Gen1PokeStats stats;

View File

@ -55,6 +55,10 @@ Gen1GameReader::Gen1GameReader(IRomReader &romReader, ISaveManager &saveManager,
, gameType_(gameType)
, localization_((uint8_t)language)
{
if(language == LocalizationLanguage::MAX)
{
localization_ = static_cast<uint8_t>(gen1_determineGameLanguage(romReader, gameType));
}
}
const char *Gen1GameReader::getPokemonName(uint8_t index) const