Poke_Transporter_GB/source/pokemon_data.cpp
Philippe Symons 532a095d77 Implement zx0 compression
Compress data tables with the ZX0 compression algorithm
2025-04-24 21:14:48 +02:00

231 lines
6.2 KiB
C++

#include "pokemon_data.h"
#include "zx0_decompressor.h"
#include "EXP_GROUPS_zx0_bin.h"
#include "GENDER_RATIO_zx0_bin.h"
#include "NUM_ABILITIES_zx0_bin.h"
#include "FIRST_MOVES_zx0_bin.h"
#include "EVOLUTIONS_zx0_bin.h"
#include "POWER_POINTS_zx0_bin.h"
#include "gen_1_index_array_zx0_bin.h"
#include "EVENT_PKMN_zx0_bin.h"
#include "TYPES_zx0_bin.h"
#include "MOVESETS_zx0_bin.h"
#include "gen_1_Jpn_char_array_zx0_bin.h"
#include "gen_1_Eng_char_array_zx0_bin.h"
#include "gen_1_FreGer_char_array_zx0_bin.h"
#include "gen_1_ItaSpa_char_array_zx0_bin.h"
#include "gen_2_Jpn_char_array_zx0_bin.h"
#include "gen_2_Eng_char_array_zx0_bin.h"
#include "gen_2_FreGer_char_array_zx0_bin.h"
#include "gen_2_ItaSpa_char_array_zx0_bin.h"
#include "gen_3_Jpn_char_array_zx0_bin.h"
#include "gen_3_Intern_char_array_zx0_bin.h"
#include <tonc.h>
// Indexes found here: https://bulbapedia.bulbagarden.net/wiki/Experience#In_the_core_series
const u32 EXP_MAXIMUMS[6] = {
med_fast_max,
erratic_max,
flux_max,
med_slow_max,
fast_max,
slow_max};
const int GENDER_THRESHOLDS[2][8]{
{-1, 2, 4, 8, 12, 14, -1, -1},
{-1, 31, 63, 127, 191, 225, -1, -1}};
static void load_table(u8 *table, const u8* source, bool &loadedBool)
{
if(loadedBool)
{
return;
}
zx0_decompressor_set_input(source);
zx0_decompressor_read(table, zx0_decompressor_get_decompressed_size());
loadedBool = true;
}
PokemonTables::PokemonTables()
: exp_groups_loaded(false)
, gender_ratios_loaded(false)
, num_abilities_loaded(false)
, power_points_loaded(false)
, gen_1_index_array_loaded(false)
, event_pkmn_loaded(false)
, types_loaded(false)
, input_charset_type(0)
, gen3_charset_type(0)
, movesets_loaded(false)
{
}
void PokemonTables::load_exp_groups()
{
load_table(EXP_GROUPS, EXP_GROUPS_zx0_bin, exp_groups_loaded);
}
void PokemonTables::load_gender_ratios()
{
load_table(GENDER_RATIO, GENDER_RATIO_zx0_bin, gender_ratios_loaded);
}
void PokemonTables::load_num_abilities()
{
load_table((uint8_t*)NUM_ABILITIES, NUM_ABILITIES_zx0_bin, num_abilities_loaded);
}
void PokemonTables::load_first_moves()
{
load_table(FIRST_MOVES, FIRST_MOVES_zx0_bin, first_moves_loaded);
}
void PokemonTables::load_evolutions()
{
load_table(EVOLUTIONS, EVOLUTIONS_zx0_bin, evolutions_loaded);
}
void PokemonTables::load_power_points()
{
load_table(POWER_POINTS, POWER_POINTS_zx0_bin, power_points_loaded);
}
void PokemonTables::load_gen1_index_array()
{
load_table(gen_1_index_array, gen_1_index_array_zx0_bin, gen_1_index_array_loaded);
}
void PokemonTables::load_event_pkmn()
{
load_table((uint8_t*)EVENT_PKMN, EVENT_PKMN_zx0_bin, event_pkmn_loaded);
}
void PokemonTables::load_types()
{
load_table((uint8_t*)TYPES, TYPES_zx0_bin, types_loaded);
}
void PokemonTables::load_input_charset(byte gen, byte lang)
{
const u8 desired_charset = (gen << 4) | (lang);
if(input_charset_type == desired_charset)
{
return;
}
load_localized_charset(input_charset, gen, lang);
input_charset_type = desired_charset;
}
void PokemonTables::load_gen3_charset(byte lang)
{
// transform lang into the value that would get stored in gen3_charset_index
if(lang == KOR_ID)
{
lang = JPN_ID;
}
else if(lang != JPN_ID)
{
lang = ENG_ID;
}
if(gen3_charset_type == lang)
{
return;
}
load_localized_charset(gen3_charset, 3, lang);
gen3_charset_type = lang;
}
void PokemonTables::load_movesets()
{
load_table((uint8_t*)MOVESETS, MOVESETS_zx0_bin, movesets_loaded);
}
u32 PokemonTables::get_max_exp(int index_num)
{
load_exp_groups();
int exp_group = EXP_GROUPS[index_num];
u32 exp_max = EXP_MAXIMUMS[exp_group];
u32 test = exp_max;
return test;
}
u8 PokemonTables::get_gender_threshold(int index_num, bool is_gen_3)
{
load_gender_ratios();
return GENDER_THRESHOLDS[is_gen_3][GENDER_RATIO[index_num]];
}
// If the Pokemon has two abilities it returns a 1, since ability 1 is valid. Otherwise it returns 0
bool PokemonTables::get_num_abilities(int index_num)
{
load_num_abilities();
return NUM_ABILITIES[index_num];
}
bool PokemonTables::can_learn_move(int pkmn_index, int move_index)
{
load_movesets();
load_evolutions();
byte data_byte = MOVESETS[pkmn_index][move_index / 8];
data_byte |= MOVESETS[EVOLUTIONS[pkmn_index]][move_index / 8]; // add in the previous evolution's moves (if they exist)
data_byte |= MOVESETS[EVOLUTIONS[EVOLUTIONS[pkmn_index]]][move_index / 8]; // add in the first evolution's moves (if they exist)
return (data_byte >> (7 - (move_index % 8))) & 0x1;
}
byte PokemonTables::get_earliest_move(int index_num)
{
load_first_moves();
return FIRST_MOVES[index_num];
}
byte PokemonTables::get_gen_3_char(u16 input_char)
{
return get_char_from_charset(gen3_charset, input_char);
}
static const u8 *localization_charset_files[]
{
gen_1_Jpn_char_array_zx0_bin,
gen_1_Eng_char_array_zx0_bin,
gen_1_FreGer_char_array_zx0_bin,
gen_1_FreGer_char_array_zx0_bin,
gen_1_ItaSpa_char_array_zx0_bin,
gen_1_ItaSpa_char_array_zx0_bin,
0,
gen_2_Jpn_char_array_zx0_bin,
gen_2_Eng_char_array_zx0_bin,
gen_2_FreGer_char_array_zx0_bin,
gen_2_FreGer_char_array_zx0_bin,
gen_2_ItaSpa_char_array_zx0_bin,
gen_2_ItaSpa_char_array_zx0_bin,
0,
gen_3_Jpn_char_array_zx0_bin,
gen_3_Intern_char_array_zx0_bin,
gen_3_Intern_char_array_zx0_bin,
gen_3_Intern_char_array_zx0_bin,
gen_3_Intern_char_array_zx0_bin,
gen_3_Intern_char_array_zx0_bin,
gen_3_Jpn_char_array_zx0_bin
};
void load_localized_charset(u16 *output_char_array, byte gen, byte lang)
{
zx0_decompressor_set_input(localization_charset_files[(gen - 1) * 7 + (lang - 1)]);
zx0_decompressor_read((u8*)output_char_array, sizeof(u16) * 256);
}
byte get_char_from_charset(const u16 *charset, u16 input_char)
{
u16 i = 0;
while(i < 256)
{
if (charset[i] == input_char)
{
return i;
}
++i;
}
return 0;
}