Implement OT name preservation for Gen 1 and 2 using Markings

This commit is contained in:
Lorenzooone 2023-12-27 04:25:29 +01:00
parent c97e951ac2
commit b5ae450131
43 changed files with 166 additions and 21 deletions

View File

@ -34,6 +34,7 @@ The "Act as" option allows one to choose whether the console will act as the mai
- Trading across Generations is a lossy operation. As such, some information (like ribbons) will be lost!!!
- You will not be able to trade Pokémon which did not exist in the target games.
- These include: Unown ? and !, all Shiny Unown but I and V, certain Female Shiny Pokémon, Pokémon holding Mail.
- When trading, markings may be applied to Pokémon from Gen 1 or Gen 2 games to preserve some data regarding the OT. Editing the markings may cause data loss.
### Clock Settings
In the Settings inside of the Main Menu, the Clock Settings will be available if you're playing Pokémon Ruby/Sapphire/Emerald.

View File

@ -0,0 +1,2 @@
.aEP&
£P@göP»NP@€†„<E280A0>“ŽP‡P†ˆˆP<CB86>‡P‰€ŠP<C5A0>€ €‡P‰€ŠP<C5A0>‡P‰€ˆŒ„P<E2809E>€€™”P†€˜P‰€<E280B0>€”P†€˜P‰ <20>”P†€˜P<CB9C>ˆ<10>”„P†€˜P‰<04>”„P„†ˆP†€˜P‰Ž‡<C5BD>P<EFBFBD>$†€˜P‰”€<E2809D>P<EFBFBD>€†€˜P<CB9C>ˆ<EFBFBD><CB86>ŽP†„<E2809E>P€‡P‰€ †ˆŽP€‡PˆˆP<CB86>”Ž•ŽP†ŽƒP‡ˆŽP“†ŽƒP‰”ˆ<CB86>†”€ƒŽP€‡P€†®«£Pƒ€<C692>ˆ ‰€ŠP<C5A0>€Œ„P<E2809E> ‰€ŠP<C5A0><E28093>‰€ˆŒ„P<E2809E>”„•Ž€‰„€<E2809E>P<EFBFBD>ŽŒœP‰Ž‡<C5BD>P<EFBFBD>€Œ„P ‰Ž‡<C5BD>P<EFBFBD><E28093>‰”€<E2809D>P<EFBFBD>”„•Ž€ŽŽP‡ˆŽP“Ž€ŽŽP<C5BD>€ŽŽPƒ<10>€”P<E280B9>ŽŒœP<C593><08>ˆ<EFBFBD><CB86>ŽP<C5BD>”Ž•Ž<10>€“€PŠ€ŒŽ<C592>„ƒP€‡P‰€„ƒP‡€P<E282AC>„†ˆP‰„€<E2809E>PމŽP€‡P‰€€ŽŽP€‡P†Ž“P€‡P‰€ ‡€P<E282AC>€”Pˆ•„Pƒ€<C692>ˆˆ•„PŠ€ŒŽ¨«¡¤±P“‡ŽŒ ˜ŽP€‡P˜ŽP

View File

@ -0,0 +1 @@
 <07><><EFBFBD>P<EFBFBD> <09><>P<> <0B><>P,< <0B><><EFBFBD>P, <0B><>P,<<1B><>P<EFBFBD><50><02><><EFBFBD><EFBFBD>P<EFBFBD><02><><EFBFBD>P <0B><02><08>P <0B><02><><19>P<EFBFBD><02><><EFBFBD> P <02><>P<><50>

View File

@ -0,0 +1 @@
°売P<EFBFBD>遭P猿㍾P剛<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
槍ケ€仲P園P剛<EFBFBD>

View File

@ -0,0 +1 @@
宙虚яP橿月

View File

@ -0,0 +1 @@
<EFBFBD>給事P€仲P園P剛<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD>泣P鉛笈ы

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
宙虚яPム壕

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD>ォ」Pム壕щ

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
暢ォ。、アP島詞

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>

View File

@ -0,0 +1 @@
綜鋳傘€仲P<EFBFBD><EFBFBD>P鵠歯傘

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD>€給傘€仲P<EFBFBD><EFBFBD>P鵠歯傘

View File

@ -0,0 +1 @@
<1B>P<EFBFBD><50><EFBFBD> P ⑪P,<

View File

@ -0,0 +1 @@
P<>

View File

@ -0,0 +1 @@
<07><><EFBFBD>P<EFBFBD><08>P <0B><>P,<

View File

@ -0,0 +1 @@
ァャP鞄輝 ュャ⑰,

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><19>P<EFBFBD>

View File

@ -0,0 +1 @@
<ィ絮鞄輝 ュャ⑰,

View File

@ -0,0 +1,2 @@
aEP&
£P

View File

@ -0,0 +1 @@
g<04>NP

View File

@ -0,0 +1 @@
€剩輝<EFBFBD>遭P鉛€恒鵠<EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
資傘㊧綜P梼

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -24,5 +24,6 @@ u8 get_pokemon_gender_kind_gen2(u8, u8, u8);
const u8* get_pokemon_name_gen2_gen3_enc(int, u8, u8);
const u8* get_pokemon_name_gen2(int, u8, u8, u8*);
const u8* get_default_trainer_name_gen2(u8, u8*);
const u8* get_actual_ot_name(const u8*, u8, u8, u8);
#endif

View File

@ -12,7 +12,7 @@ void alter_nature(struct gen3_mon_data_unenc*, u8);
void set_alter_data(struct gen3_mon_data_unenc*, struct alternative_data_gen3*);
void preload_if_fixable(struct gen3_mon_data_unenc*);
void convert_trainer_name_gen3_to_gen12(u8*, u8*, u8, u8);
void convert_trainer_name_gen3_to_gen12(u8*, u8*, u8, u8, u8);
void convert_trainer_name_gen12_to_gen3(u8*, u8*, u8, u8, u8);
u8 gen3_to_gen2(struct gen2_mon*, struct gen3_mon_data_unenc*, u32);

View File

@ -174,6 +174,10 @@
#define ROAMER_ENCOUNTER 2
#define UNOWN_ENCOUNTER 3
#define SPECIAL_NAME_MARKS_VALUE 0xF
//#define ALLOW_KOREAN
#define NUM_LANGUAGES 8
#define NUM_POKEMON_NAME_LANGUAGES 4
#define FIRST_VALID_LANGUAGE 1
@ -186,6 +190,11 @@
#define GERMAN_LANGUAGE 5
#define KOREAN_LANGUAGE 6
#define SPANISH_LANGUAGE 7
#ifdef ALLOW_KOREAN
#define ALL_LANGUAGES ((1 << JAPANESE_LANGUAGE) | (1 << ENGLISH_LANGUAGE) | (1 << FRENCH_LANGUAGE) | (1 << ITALIAN_LANGUAGE) | (1 << GERMAN_LANGUAGE) | (1 << KOREAN_LANGUAGE) | (1 << SPANISH_LANGUAGE))
#else
#define ALL_LANGUAGES ((1 << JAPANESE_LANGUAGE) | (1 << ENGLISH_LANGUAGE) | (1 << FRENCH_LANGUAGE) | (1 << ITALIAN_LANGUAGE) | (1 << GERMAN_LANGUAGE) | (1 << SPANISH_LANGUAGE))
#endif
#define GET_LANGUAGE_IS_JAPANESE(x) ((x) == JAPANESE_LANGUAGE)
#define GET_LANGUAGE_NICKNAME_LIMIT(x) (GET_LANGUAGE_IS_JAPANESE(x) ? NICKNAME_JP_GEN3_SIZE : NICKNAME_GEN3_SIZE)
@ -322,11 +331,13 @@ struct gen3_mon {
u8 is_bad_egg : 1;
u8 has_species : 1;
u8 use_egg_name : 1;
u8 unused : 5;
u8 block_box_rs : 1;
u8 unused : 4;
u8 ot_name[OT_NAME_GEN3_MAX_SIZE];
u8 marks;
u8 marks : 4;
u8 unused2 : 4;
u16 checksum;
u16 unk;
u16 unused3;
u32 enc_data[ENC_DATA_SIZE>>2];
u32 status;
u8 level;

View File

@ -9,6 +9,8 @@
#include "pokemon_gender_bin.h"
#include "pokemon_stats_gen1_bin.h"
#include "pokemon_stats_bin.h"
#include "default_names_int_gen_i_ii_bin.h"
#include "default_names_jpn_gen_i_ii_bin.h"
const u8* set_buffer_with_gen2(const u8*, u8, u8*);
u16 get_stat_exp_contribution(u16);
@ -228,6 +230,43 @@ const u8* get_default_trainer_name_gen2(u8 language, u8* buffer) {
return set_buffer_with_gen2(get_default_trainer_name(language), language, buffer);
}
const u8* get_actual_ot_name(const u8* gen2_ot_name, u8 is_jp, u8 terminator_stop, u8 language_target) {
const u8* names_list = default_names_int_gen_i_ii_bin;
if(is_jp)
names_list = default_names_jpn_gen_i_ii_bin;
u8 names_size = names_list[0] - 1;
u8 num_entries = names_list[1];
u16 curr_pos = 2;
u8 found = 0;
for(int i = 0; i < num_entries; i++) {
int diff = 0;
for(int j = 0; j < names_size; j++) {
diff = gen2_ot_name[j] - names_list[curr_pos + j];
if(diff != 0)
break;
if(terminator_stop && (gen2_ot_name[j] == GEN2_EOL))
break;
}
if(diff == 0) {
if((language_target == 0) || (names_list[curr_pos + names_size] & (1 << language_target))) {
found = 1;
break;
}
}
// Use the fact that the list is sorted
if(diff < 0)
break;
curr_pos += names_size + 1;
}
if(!found)
return NULL;
return &names_list[curr_pos];
}
u8 get_pokemon_gender_gen2(u8 index, u8 atk_ivs, u8 is_egg, u8 curr_gen) {
u8 gender_kind = get_pokemon_gender_kind_gen2(index, is_egg, curr_gen);
switch(gender_kind){

View File

@ -75,7 +75,7 @@ void convert_strings_of_gen3_generic(struct gen3_mon*, u16, u8*, u8*, u8, u8, u8
void convert_strings_of_gen12(struct gen3_mon*, u8, u8*, u8*, u8, u8);
void special_convert_strings_distribution(struct gen3_mon*, u16);
u8 text_handling_gen12_to_gen3(struct gen3_mon*, u16, u16, u8, u8*, u8*, u8, u8);
void set_language_gen12_to_gen3(struct gen3_mon*, u16, u8, u8*, u8);
void set_language_gen12_to_gen3(struct gen3_mon*, u16, u8, const u8*, const u8*, u8);
void sanitize_ot_name_gen3_to_gen12(u8*, u8*, u8, u8);
void sanitize_ot_name_gen12_to_gen3(u8*, u8*, u8);
void clean_name_gen12(u8*, u8);
@ -909,7 +909,7 @@ void sanitize_ot_name_gen12_to_gen3(u8* src, u8* dst, u8 language) {
sanitize_name_gen12_to_gen3(src, dst, get_default_trainer_name(language), gen2_name_cap, gen3_ot_name_cap);
}
void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 dst_language) {
void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 dst_language, u8 marks) {
u8 is_jp_gen3 = GET_LANGUAGE_IS_JAPANESE(src_language);
u8 is_jp_target = GET_LANGUAGE_IS_JAPANESE(dst_language);
@ -931,6 +931,26 @@ void convert_trainer_name_gen3_to_gen12(u8* src, u8* dst, u8 src_language, u8 ds
// Do some sanitization
sanitize_ot_name_gen3_to_gen12(src, dst, src_language, dst_language);
// Apply special OT Name handling with special markings value
if(marks == SPECIAL_NAME_MARKS_VALUE) {
const u8* special_name = get_actual_ot_name(dst, is_jp_target, 1, src_language);
if(special_name) {
for(size_t i = 0; i < gen12_ot_name_size; i++)
dst[i] = special_name[i];
return;
}
marks = 0;
}
// Apply special OT Name handling and 0 out certain parts of the name
if(marks > gen12_ot_name_size)
marks = 0;
size_t pos_zeros = text_gen2_size(dst, gen12_ot_name_cap) + 1;
if(marks > pos_zeros)
pos_zeros = marks;
for(; pos_zeros < gen12_ot_name_size; pos_zeros++)
dst[pos_zeros] = 0;
}
void convert_trainer_name_gen12_to_gen3(u8* src, u8* dst, u8 src_is_jp, u8 dst_language, u8 max_size) {
@ -994,7 +1014,7 @@ void convert_strings_of_gen3_generic(struct gen3_mon* src, u16 species, u8* ot_n
text_gen2_replace(nickname, gen12_nickname_cap, GEN2_DOT, GEN1_DOT);
*/
convert_trainer_name_gen3_to_gen12(src->ot_name, ot_name, src->language, target_language);
convert_trainer_name_gen3_to_gen12(src->ot_name, ot_name, src->language, target_language, src->marks);
}
void convert_strings_of_gen3(struct gen3_mon* src, u16 species, u8* ot_name, u8* ot_name_jp, u8* nickname, u8* nickname_jp, u8 is_egg, u8 is_gen2) {
@ -1271,21 +1291,54 @@ void clean_name_gen12(u8* name, u8 is_jp) {
text_gen2_replace(name, gen2_name_cap, GEN1_DOT, GEN2_DOT);
}
void set_language_gen12_to_gen3(struct gen3_mon* dst, u16 species, u8 is_egg, u8* nickname, u8 is_jp) {
void set_language_gen12_to_gen3(struct gen3_mon* dst, u16 species, u8 is_egg, const u8* ot_name, const u8* nickname, u8 is_jp) {
u8 gen2_buffer[STRING_GEN2_MAX_SIZE];
u8 int_language = get_filtered_target_int_language();
u32 possible_languages = ALL_LANGUAGES & (~(1 << JAPANESE_LANGUAGE));
u8 gen12_ot_name_size = STRING_GEN2_INT_SIZE;
if(is_jp) {
possible_languages = (1 << JAPANESE_LANGUAGE);
gen12_ot_name_size = STRING_GEN2_JP_SIZE;
}
const u8* special_name = get_actual_ot_name(ot_name, is_jp, 0, 0);
// Abuse markings to store info about the Gen 1/2 OT Name's trailing bytes
if(special_name != NULL) {
possible_languages &= special_name[gen12_ot_name_size];
dst->marks = SPECIAL_NAME_MARKS_VALUE;
}
else {
size_t end_eol = gen12_ot_name_size;
for(; end_eol > 0; end_eol--) {
if(ot_name[end_eol - 1] == GEN2_EOL)
break;
}
dst->marks = end_eol;
}
// Fix possible bad language filtering (Korean)
if(!possible_languages) {
possible_languages = ALL_LANGUAGES & (~(1 << JAPANESE_LANGUAGE));
dst->marks = 0;
}
if((!is_jp) && (get_target_int_language() == UNKNOWN_LANGUAGE)) {
u32 found_languages = 0;
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
if(text_gen2_is_same(nickname, get_pokemon_name_gen2(species, is_egg, i, gen2_buffer), STRING_GEN2_INT_CAP, STRING_GEN2_INT_CAP))
found_languages |= 1<<i;
if(found_languages && (!(found_languages & (1<<int_language))))
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
if(found_languages & (1<<i)) {
int_language = i;
break;
}
found_languages |= 1 << i;
// OT Name has priority
if(possible_languages & found_languages)
possible_languages &= found_languages;
}
if((!is_jp) && (!(possible_languages & (1 << int_language)))) {
for(size_t i = FIRST_INTERNATIONAL_VALID_LANGUAGE; i < NUM_LANGUAGES; i++)
if(possible_languages & (1 << i)) {
int_language = i;
break;
}
}
if(is_jp)
@ -1309,7 +1362,7 @@ u8 text_handling_gen12_to_gen3(struct gen3_mon* dst, u16 species, u16 swapped_ot
clean_name_gen12(nickname, is_jp);
// Handle language
set_language_gen12_to_gen3(dst, species, is_egg, nickname, is_jp);
set_language_gen12_to_gen3(dst, species, is_egg, ot_name, nickname, is_jp);
// Specially handle Celebi's event
if((species == CELEBI_SPECIES) && (!is_egg)) {

View File

@ -144,12 +144,13 @@ void load_names_gen12(struct game_data_t* game_data, struct gen2_party* party_2,
if(is_jp)
language = JAPANESE_LANGUAGE;
convert_trainer_name_gen3_to_gen12(game_data->trainer_name, trainer_name, game_data->game_identifier.language, language);
convert_trainer_name_gen3_to_gen12(game_data->trainer_name, trainer_name, game_data->game_identifier.language, language, 0);
for(size_t i = 0; i < size; i++)
if((trainer_name[i] == NO_ACTION_BYTE) || (trainer_name[i] == (NO_ACTION_BYTE-1)))
trainer_name[i] = NO_ACTION_BYTE-2;
trainer_name[size-1] = GEN2_EOL;
u8 text_size = text_gen2_size(trainer_name, size-1);
trainer_name[text_size] = GEN2_EOL;
if(!curr_gen)
return;
@ -174,9 +175,11 @@ void load_names_gen12(struct game_data_t* game_data, struct gen2_party* party_2,
src_nickname = party_1->mons[i].nickname;
}
copy_bytes(src_ot_name, ot_names, size, 0, i*size);
ot_names[(i*size)+size-1] = GEN2_EOL;
text_size = text_gen2_size(&ot_names[i*size], size-1);
ot_names[(i*size)+text_size] = GEN2_EOL;
copy_bytes(src_nickname, nicknames, size, 0, i*size);
nicknames[(i*size)+size-1] = GEN2_EOL;
text_size = text_gen2_size(&nicknames[i*size], size-1);
nicknames[(i*size)+text_size] = GEN2_EOL;
}
}

View File

@ -167,7 +167,7 @@ void sanitize_name_general_to_general(const u8* src, u8* dst, const u8* default_
size_t question_marks_count = question_marks_count_dst - question_marks_count_src;
if(question_marks_count_src > question_marks_count_dst)
question_marks_count = 0;
if((question_marks_count >= (text_general_size(dst, dst_size, dst_terminator) >> 1)) || (!text_general_size(dst, dst_size, dst_terminator)))
if((question_marks_count >= ((text_general_size(dst, dst_size, dst_terminator) + 1) >> 1)) || (!text_general_size(dst, dst_size, dst_terminator)))
text_general_copy(default_name, dst, dst_size, dst_size, dst_terminator);
}