1use std::convert::Infallible;
2use std::fmt::Display;
3
4use crate::byte_handler::{ByteHandler, ByteHandlerError, FromByteHandler};
5
6#[derive(thiserror::Error, Debug)]
8pub enum SlotIdError {
9 #[error("Non Existent Slot ID")]
11 NonExistentSlotId,
12 #[error("ByteHandler Error: {0}")]
14 ByteHandlerError(#[from] ByteHandlerError),
15 #[error("")]
17 Infallible(#[from] Infallible),
18}
19
20#[derive(Clone, Copy, Debug, PartialEq)]
29pub enum SlotId {
30 LuigiCircuit,
32 MooMooMeadows,
33 MushroomGorge,
34 ToadsFactory,
35 MarioCircuit,
36 CoconutMall,
37 DKSnowboardCross,
38 WariosGoldMine,
39 DaisyCircuit,
40 KoopaCape,
41 MapleTreeway,
42 GrumbleVolcano,
43 DryDryRuins,
44 MoonviewHighway,
45 BowsersCastle,
46 RainbowRoad,
47 GCNPeachBeach,
48 DSYoshiFalls,
49 SNESGhostValley2,
50 N64MarioRaceway,
51 N64SherbetLand,
52 GBAShyGuyBeach,
53 DSDelfinoSquare,
54 GCNWaluigiStadium,
55 DSDesertHills,
56 GBABowserCastle3,
57 N64DKJungleParkway,
58 GCNMarioCircuit,
59 SNESMarioCircuit3,
60 DSPeachGardens,
61 GCNDKMountain,
62 N64BowsersCastle,
63
64 BlockPlaza,
66 DelfinoPier,
67 FunkyStadium,
68 ChainChompWheel,
69 ThwompDesert,
70 SNESBattleCourse4,
71 GBABattleCourse3,
72 N64Skscraper,
73 GCNCookieLand,
74 DSTwilightHouse,
75
76 GalaxyColosseum,
79 WinningScene,
81 LosingScene,
83 Credits,
85}
86
87impl Display for SlotId {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 let s = match self {
91 SlotId::LuigiCircuit => "Luigi Circuit",
93 SlotId::MooMooMeadows => "Moo Moo Meadows",
94 SlotId::MushroomGorge => "Mushroom Gorge",
95 SlotId::ToadsFactory => "Toad's Factory",
96 SlotId::MarioCircuit => "Mario Circuit",
97 SlotId::CoconutMall => "Coconut Mall",
98 SlotId::DKSnowboardCross => "DK Summit",
99 SlotId::WariosGoldMine => "Wario's Gold Mine",
100 SlotId::DaisyCircuit => "Daisy Circuit",
101 SlotId::KoopaCape => "Koopa Cape",
102 SlotId::MapleTreeway => "Maple Treeway",
103 SlotId::GrumbleVolcano => "Grumble Volcano",
104 SlotId::DryDryRuins => "Dry Dry Ruins",
105 SlotId::MoonviewHighway => "Moonview Highway",
106 SlotId::BowsersCastle => "Bowser's Castle",
107 SlotId::RainbowRoad => "Rainbow Road",
108
109 SlotId::GCNPeachBeach => "GCN Peach Beach",
110 SlotId::DSYoshiFalls => "DS Yoshi Falls",
111 SlotId::SNESGhostValley2 => "SNES Ghost Valley 2",
112 SlotId::N64MarioRaceway => "N64 Mario Raceway",
113 SlotId::N64SherbetLand => "N64 Sherbet Land",
114 SlotId::GBAShyGuyBeach => "GBA Shy Guy Beach",
115 SlotId::DSDelfinoSquare => "DS Delfino Square",
116 SlotId::GCNWaluigiStadium => "GCN Waluigi Stadium",
117 SlotId::DSDesertHills => "DS Desert Hills",
118 SlotId::GBABowserCastle3 => "GBA Bowser Castle 3",
119 SlotId::N64DKJungleParkway => "N64 DK Jungle Parkway",
120 SlotId::GCNMarioCircuit => "GCN Mario Circuit",
121 SlotId::SNESMarioCircuit3 => "SNES Mario Circuit 3",
122 SlotId::DSPeachGardens => "DS Peach Gardens",
123 SlotId::GCNDKMountain => "GCN DK Mountain",
124 SlotId::N64BowsersCastle => "N64 Bowser's Castle",
125
126 SlotId::BlockPlaza => "Block Plaza",
128 SlotId::DelfinoPier => "Delfino Pier",
129 SlotId::FunkyStadium => "Funky Stadium",
130 SlotId::ChainChompWheel => "Chain Chomp Wheel",
131 SlotId::ThwompDesert => "Thwomp Desert",
132 SlotId::SNESBattleCourse4 => "SNES Battle Course 4",
133 SlotId::GBABattleCourse3 => "GBA Battle Course 3",
134 SlotId::N64Skscraper => "N64 Skyscraper",
135 SlotId::GCNCookieLand => "GCN Cookie Land",
136 SlotId::DSTwilightHouse => "DS Twilight House",
137
138 SlotId::GalaxyColosseum => "Galaxy Colosseum",
140 SlotId::WinningScene => "Winning Scene",
141 SlotId::LosingScene => "Losing Scene",
142 SlotId::Credits => "Credits",
143 };
144
145 write!(f, "{}", s)
146 }
147}
148
149impl From<SlotId> for u8 {
151 fn from(value: SlotId) -> u8 {
152 match value {
153 SlotId::LuigiCircuit => 0x08,
154 SlotId::MooMooMeadows => 0x01,
155 SlotId::MushroomGorge => 0x02,
156 SlotId::ToadsFactory => 0x04,
157 SlotId::MarioCircuit => 0x00,
158 SlotId::CoconutMall => 0x05,
159 SlotId::DKSnowboardCross => 0x06,
160 SlotId::WariosGoldMine => 0x07,
161 SlotId::DaisyCircuit => 0x09,
162 SlotId::KoopaCape => 0x0F,
163 SlotId::MapleTreeway => 0x0B,
164 SlotId::GrumbleVolcano => 0x03,
165 SlotId::DryDryRuins => 0x0E,
166 SlotId::MoonviewHighway => 0x0A,
167 SlotId::BowsersCastle => 0x0C,
168 SlotId::RainbowRoad => 0x0D,
169 SlotId::GCNPeachBeach => 0x10,
170 SlotId::DSYoshiFalls => 0x14,
171 SlotId::SNESGhostValley2 => 0x19,
172 SlotId::N64MarioRaceway => 0x1A,
173 SlotId::N64SherbetLand => 0x1B,
174 SlotId::GBAShyGuyBeach => 0x1F,
175 SlotId::DSDelfinoSquare => 0x17,
176 SlotId::GCNWaluigiStadium => 0x12,
177 SlotId::DSDesertHills => 0x15,
178 SlotId::GBABowserCastle3 => 0x1E,
179 SlotId::N64DKJungleParkway => 0x1D,
180 SlotId::GCNMarioCircuit => 0x11,
181 SlotId::SNESMarioCircuit3 => 0x18,
182 SlotId::DSPeachGardens => 0x16,
183 SlotId::GCNDKMountain => 0x13,
184 SlotId::N64BowsersCastle => 0x1C,
185 SlotId::BlockPlaza => 0x21,
186 SlotId::DelfinoPier => 0x20,
187 SlotId::FunkyStadium => 0x23,
188 SlotId::ChainChompWheel => 0x22,
189 SlotId::ThwompDesert => 0x24,
190 SlotId::SNESBattleCourse4 => 0x27,
191 SlotId::GBABattleCourse3 => 0x28,
192 SlotId::N64Skscraper => 0x29,
193 SlotId::GCNCookieLand => 0x25,
194 SlotId::DSTwilightHouse => 0x26,
195 SlotId::GalaxyColosseum => 0xC9,
196 SlotId::WinningScene => 0x37,
197 SlotId::LosingScene => 0x38,
198 SlotId::Credits => 0x3A,
199 }
200 }
201}
202
203impl TryFrom<u8> for SlotId {
210 type Error = SlotIdError;
211 fn try_from(value: u8) -> Result<Self, Self::Error> {
212 match value {
213 0x08 => Ok(SlotId::LuigiCircuit),
214 0x01 => Ok(SlotId::MooMooMeadows),
215 0x02 => Ok(SlotId::MushroomGorge),
216 0x04 => Ok(SlotId::ToadsFactory),
217 0x00 => Ok(SlotId::MarioCircuit),
218 0x05 => Ok(SlotId::CoconutMall),
219 0x06 => Ok(SlotId::DKSnowboardCross),
220 0x07 => Ok(SlotId::WariosGoldMine),
221 0x09 => Ok(SlotId::DaisyCircuit),
222 0x0F => Ok(SlotId::KoopaCape),
223 0x0B => Ok(SlotId::MapleTreeway),
224 0x03 => Ok(SlotId::GrumbleVolcano),
225 0x0E => Ok(SlotId::DryDryRuins),
226 0x0A => Ok(SlotId::MoonviewHighway),
227 0x0C => Ok(SlotId::BowsersCastle),
228 0x0D => Ok(SlotId::RainbowRoad),
229 0x10 => Ok(SlotId::GCNPeachBeach),
230 0x14 => Ok(SlotId::DSYoshiFalls),
231 0x19 => Ok(SlotId::SNESGhostValley2),
232 0x1A => Ok(SlotId::N64MarioRaceway),
233 0x1B => Ok(SlotId::N64SherbetLand),
234 0x1F => Ok(SlotId::GBAShyGuyBeach),
235 0x17 => Ok(SlotId::DSDelfinoSquare),
236 0x12 => Ok(SlotId::GCNWaluigiStadium),
237 0x15 => Ok(SlotId::DSDesertHills),
238 0x1E => Ok(SlotId::GBABowserCastle3),
239 0x1D => Ok(SlotId::N64DKJungleParkway),
240 0x11 => Ok(SlotId::GCNMarioCircuit),
241 0x18 => Ok(SlotId::SNESMarioCircuit3),
242 0x16 => Ok(SlotId::DSPeachGardens),
243 0x13 => Ok(SlotId::GCNDKMountain),
244 0x1C => Ok(SlotId::N64BowsersCastle),
245 0x21 => Ok(SlotId::BlockPlaza),
246 0x20 => Ok(SlotId::DelfinoPier),
247 0x23 => Ok(SlotId::FunkyStadium),
248 0x22 => Ok(SlotId::ChainChompWheel),
249 0x24 => Ok(SlotId::ThwompDesert),
250 0x27 => Ok(SlotId::SNESBattleCourse4),
251 0x28 => Ok(SlotId::GBABattleCourse3),
252 0x29 => Ok(SlotId::N64Skscraper),
253 0x25 => Ok(SlotId::GCNCookieLand),
254 0x26 => Ok(SlotId::DSTwilightHouse),
255 0xC9 => Ok(SlotId::GalaxyColosseum),
256 0x37 => Ok(SlotId::WinningScene),
257 0x38 => Ok(SlotId::LosingScene),
258 0x3A => Ok(SlotId::Credits),
259 _ => Err(SlotIdError::NonExistentSlotId),
260 }
261 }
262}
263
264impl FromByteHandler for SlotId {
266 type Err = SlotIdError;
267 fn from_byte_handler<T>(handler: T) -> Result<Self, Self::Err>
269 where
270 T: TryInto<ByteHandler>,
271 Self::Err: From<T::Error>,
272 {
273 (handler.try_into()?.copy_byte(0) >> 2).try_into()
274 }
275}