1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Game version detection and configuration
use serde::{Deserialize, Serialize};
/// Game language/region
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum GameLanguage {
/// English (USA/Europe)
#[default]
English,
/// Japanese
Japanese,
/// French
French,
/// German
German,
/// Italian
Italian,
/// Spanish
Spanish,
/// Korean
Korean,
}
/// Game family grouping
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum GameFamily {
/// Diamond and Pearl
DP,
/// Platinum
Platinum,
/// HeartGold and SoulSilver
HGSS,
}
/// Specific game version
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Game {
Diamond,
Pearl,
Platinum,
HeartGold,
SoulSilver,
}
impl Game {
/// Get the game family for this game
pub fn family(&self) -> GameFamily {
match self {
Game::Diamond | Game::Pearl => GameFamily::DP,
Game::Platinum => GameFamily::Platinum,
Game::HeartGold | Game::SoulSilver => GameFamily::HGSS,
}
}
/// Get the map header size in bytes for this game
pub fn map_header_size(&self) -> usize {
// All Gen 4 games use 24-byte headers in binary format
24
}
}
impl GameFamily {
/// Returns a representative game for this family.
///
/// Use this only when a specific [`Game`] is required but only a family is known
/// (e.g. fallback workspace construction). Prefer [`Workspace::open`] when possible.
pub fn default_game(self) -> Game {
match self {
GameFamily::DP => Game::Diamond,
GameFamily::Platinum => Game::Platinum,
GameFamily::HGSS => Game::HeartGold,
}
}
/// Get the map header size in bytes for this game family
pub fn map_header_size(&self) -> usize {
24
}
/// Get the null encounter file ID for this game family
pub fn null_encounter_id(&self) -> u16 {
match self {
GameFamily::DP | GameFamily::Platinum => 0xFFFF,
GameFamily::HGSS => 0xFF,
}
}
}
impl GameLanguage {
pub fn from_region_code(code: char) -> Self {
match code {
'J' => GameLanguage::Japanese,
'E' => GameLanguage::English,
'P' => GameLanguage::English, // Europe uses English text banks
'F' => GameLanguage::French,
'D' => GameLanguage::German,
'I' => GameLanguage::Italian,
'S' => GameLanguage::Spanish,
'K' => GameLanguage::Korean,
_ => GameLanguage::English,
}
}
pub fn is_japanese(&self) -> bool {
matches!(self, GameLanguage::Japanese)
}
/// Return the DSPRE/Decomp locale key for this language.
pub fn locale_key(&self) -> &'static str {
match self {
GameLanguage::English => "en_US",
GameLanguage::Japanese => "ja_JP",
GameLanguage::French => "fr_FR",
GameLanguage::German => "de_DE",
GameLanguage::Italian => "it_IT",
GameLanguage::Spanish => "es_ES",
GameLanguage::Korean => "ko_KR",
}
}
}