rustboy_core/
memory.rs

1use core::fmt::{Debug, Formatter};
2use serde::{Deserialize, Serialize};
3use crate::internal::memory::oam::ObjectAttributes;
4use crate::memory::Licensee::{NewLicensee, OldLicensee};
5
6#[derive(Copy, Clone)]
7pub struct OAMObject {
8  pub lcd_y: u8,
9  pub lcd_x: u8,
10  pub tile_index: u8,
11  pub attributes: ObjectAttributes,
12}
13
14#[derive(Copy, Clone)]
15pub enum ROMSize {
16  KB32,
17  KB64,
18  KB128,
19  KB256,
20  KB512,
21  MB1,
22  MB2,
23  MB4,
24  MB8,
25}
26
27pub enum Licensee {
28  OldLicensee(u8),
29  NewLicensee(char, char),
30}
31
32impl Licensee {
33  pub fn from_bytes(rom_bytes: &[u8]) -> Self {
34    let licensee_code = rom_bytes[0x14B];
35    if licensee_code == 0x33 {
36      NewLicensee(
37        rom_bytes[0x0144] as char,
38        rom_bytes[0x0145] as char,
39      )
40    } else {
41      OldLicensee(licensee_code)
42    }
43  }
44
45  pub fn is_licensed_by_nintendo(&self) -> bool {
46    match self {
47      OldLicensee(code) => *code == 0x01,
48      NewLicensee(upper, lower) => *upper == '0' && *lower == '1'
49    }
50  }
51
52  pub fn get_name(&self) -> String {
53    let name = match self {
54      OldLicensee(code) => match *code {
55        0x00 => "None",
56        0x01 => "Nintendo",
57        0x08 => "Capcom",
58        0x09 => "Hot-B",
59        0x0A => "Jaleco",
60        0x0B => "Coconuts Japan",
61        0x0C => "Elite Systems",
62        0x13 => "EA (Electronic Arts)",
63        0x18 => "Hudsonsoft",
64        0x19 => "ITC Entertainment",
65        0x1A => "Yanoman",
66        0x1D => "Japan Clary",
67        0x1F => "Virgin Interactive",
68        0x24 => "PCM Complete",
69        0x25 => "San-X",
70        0x28 => "Kotobuki Systems",
71        0x29 => "Seta",
72        0x30 => "Infogrames",
73        0x31 => "Nintendo",
74        0x32 => "Bandai",
75        0x34 => "Konami",
76        0x35 => "HectorSoft",
77        0x38 => "Capcom",
78        0x39 => "Banpresto",
79        0x3C => ".Entertainment i",
80        0x3E => "Gremlin",
81        0x41 => "Ubisoft",
82        0x42 => "Atlus",
83        0x44 => "Malibu",
84        0x46 => "Angel",
85        0x47 => "Spectrum Holoby",
86        0x49 => "Irem",
87        0x4A => "Virgin Interactive",
88        0x4D => "Malibu",
89        0x4F => "U.S. Gold",
90        0x50 => "Absolute",
91        0x51 => "Acclaim",
92        0x52 => "Activision",
93        0x53 => "American Sammy",
94        0x54 => "GameTek",
95        0x55 => "Park Place",
96        0x56 => "LJN",
97        0x57 => "Matchbox",
98        0x59 => "Milton Bradley",
99        0x5A => "Mindscape",
100        0x5B => "Romstar",
101        0x5C => "Naxat Soft",
102        0x5D => "Tradewest",
103        0x60 => "Titus",
104        0x61 => "Virgin Interactive",
105        0x67 => "Ocean Interactive",
106        0x69 => "EA (Electronic Arts)",
107        0x6E => "Elite Systems",
108        0x6F => "Electro Brain",
109        0x70 => "Infogrames",
110        0x71 => "Interplay",
111        0x72 => "Broderbund",
112        0x73 => "Sculptered Soft",
113        0x75 => "The Sales Curve",
114        0x78 => "t.hq",
115        0x79 => "Accolade",
116        0x7A => "Triffix Entertainment",
117        0x7C => "Microprose",
118        0x7F => "Kemco",
119        0x80 => "Misawa Entertainment",
120        0x83 => "Lozc",
121        0x86 => "Tokuma Shoten Intermedia",
122        0x8B => "Bullet-Proof Software",
123        0x8C => "Vic Tokai",
124        0x8E => "Ape",
125        0x8F => "I’Max",
126        0x91 => "Chunsoft Co.",
127        0x92 => "Video System",
128        0x93 => "Tsubaraya Productions Co.",
129        0x95 => "Varie Corporation",
130        0x96 => "Yonezawa/S’Pal",
131        0x97 => "Kaneko",
132        0x99 => "Arc",
133        0x9A => "Nihon Bussan",
134        0x9B => "Tecmo",
135        0x9C => "Imagineer",
136        0x9D => "Banpresto",
137        0x9F => "Nova",
138        0xA1 => "Hori Electric",
139        0xA2 => "Bandai",
140        0xA4 => "Konami",
141        0xA6 => "Kawada",
142        0xA7 => "Takara",
143        0xA9 => "Technos Japan",
144        0xAA => "Broderbund",
145        0xAC => "Toei Animation",
146        0xAD => "Toho",
147        0xAF => "Namco",
148        0xB0 => "acclaim",
149        0xB1 => "ASCII or Nexsoft",
150        0xB2 => "Bandai",
151        0xB4 => "Square Enix",
152        0xB6 => "HAL Laboratory",
153        0xB7 => "SNK",
154        0xB9 => "Pony Canyon",
155        0xBA => "Culture Brain",
156        0xBB => "Sunsoft",
157        0xBD => "Sony Imagesoft",
158        0xBF => "Sammy",
159        0xC0 => "Taito",
160        0xC2 => "Kemco",
161        0xC3 => "Squaresoft",
162        0xC4 => "Tokuma Shoten Intermedia",
163        0xC5 => "Data East",
164        0xC6 => "Tonkinhouse",
165        0xC8 => "Koei",
166        0xC9 => "UFL",
167        0xCA => "Ultra",
168        0xCB => "Vap",
169        0xCC => "Use Corporation",
170        0xCD => "Meldac",
171        0xCE => ".Pony Canyon or",
172        0xCF => "Angel",
173        0xD0 => "Taito",
174        0xD1 => "Sofel",
175        0xD2 => "Quest",
176        0xD3 => "Sigma Enterprises",
177        0xD4 => "ASK Kodansha Co.",
178        0xD6 => "Naxat Soft",
179        0xD7 => "Copya System",
180        0xD9 => "Banpresto",
181        0xDA => "Tomy",
182        0xDB => "LJN",
183        0xDD => "NCS",
184        0xDE => "Human",
185        0xDF => "Altron",
186        0xE0 => "Jaleco",
187        0xE1 => "Towa Chiki",
188        0xE2 => "Yutaka",
189        0xE3 => "Varie",
190        0xE5 => "Epcoh",
191        0xE7 => "Athena",
192        0xE8 => "Asmik ACE Entertainment",
193        0xE9 => "Natsume",
194        0xEA => "King Records",
195        0xEB => "Atlus",
196        0xEC => "Epic/Sony Records",
197        0xEE => "IGS",
198        0xF0 => "A Wave",
199        0xF3 => "Extreme Entertainment",
200        0xFF => "LJN",
201        _ => "Unknown"
202      },
203      NewLicensee(upper, lower) => match (*upper, *lower) {
204        ('0', '0') => "None",
205        ('0', '1') => "Nintendo R&D1",
206        ('0', '8') => "Capcom",
207        ('1', '3') => "Electronic Arts",
208        ('1', '8') => "Hudson Soft",
209        ('1', '9') => "b-ai",
210        ('2', '0') => "kss",
211        ('2', '2') => "pow",
212        ('2', '4') => "PCM Complete",
213        ('2', '5') => "san-x",
214        ('2', '8') => "Kemco Japan",
215        ('2', '9') => "seta",
216        ('3', '0') => "Viacom",
217        ('3', '1') => "Nintendo",
218        ('3', '2') => "Bandai",
219        ('3', '3') => "Ocean/Acclaim",
220        ('3', '4') => "Konami",
221        ('3', '5') => "Hector",
222        ('3', '7') => "Taito",
223        ('3', '8') => "Hudson",
224        ('3', '9') => "Banpresto",
225        ('4', '1') => "Ubi Soft",
226        ('4', '2') => "Atlus",
227        ('4', '4') => "Malibu",
228        ('4', '6') => "angel",
229        ('4', '7') => "Bullet-Proof",
230        ('4', '9') => "irem",
231        ('5', '0') => "Absolute",
232        ('5', '1') => "Acclaim",
233        ('5', '2') => "Activision",
234        ('5', '3') => "American sammy",
235        ('5', '4') => "Konami",
236        ('5', '5') => "Hi tech entertainment",
237        ('5', '6') => "LJN",
238        ('5', '7') => "Matchbox",
239        ('5', '8') => "Mattel",
240        ('5', '9') => "Milton Bradley",
241        ('6', '0') => "Titus",
242        ('6', '1') => "Virgin",
243        ('6', '4') => "LucasArts",
244        ('6', '7') => "Ocean",
245        ('6', '9') => "Electronic Arts",
246        ('7', '0') => "Infogrames",
247        ('7', '1') => "Interplay",
248        ('7', '2') => "Broderbund",
249        ('7', '3') => "sculptured",
250        ('7', '5') => "sci",
251        ('7', '8') => "THQ",
252        ('7', '9') => "Accolade",
253        ('8', '0') => "misawa",
254        ('8', '3') => "lozc",
255        ('8', '6') => "Tokuma Shoten Intermedia",
256        ('8', '7') => "Tsukuda Original",
257        ('9', '1') => "Chunsoft",
258        ('9', '2') => "Video system",
259        ('9', '3') => "Ocean/Acclaim",
260        ('9', '5') => "Varie",
261        ('9', '6') => "Yonezawa/s’pal",
262        ('9', '7') => "Kaneko",
263        ('9', '9') => "Pack in soft",
264        ('9', 'H') => "Bottom Up",
265        ('A', '4') => "Konami (Yu-Gi-Oh!)",
266        _ => "Unknown"
267      }
268    };
269    String::from(name)
270  }
271}
272
273#[derive(Copy, Clone)]
274pub enum CartridgeType {
275  MBC,
276  MBC1,
277  MBC2,
278  MMM01,
279  MBC3,
280  MBC5,
281  MBC6,
282  MBC7,
283  PocketCamera,
284  Bandai,
285  HuC3,
286  HuC1,
287}
288
289impl CartridgeType {
290  pub fn from_byte(byte: u8) -> Self {
291    match byte {
292      0x00 => CartridgeType::MBC,
293      0x01..=0x03 => CartridgeType::MBC1,
294      0x05..=0x06 => CartridgeType::MBC2,
295      0x0B..=0x0D => CartridgeType::MMM01,
296      0x0F..=0x13 => CartridgeType::MBC3,
297      0x19..=0x1E => CartridgeType::MBC5,
298      0x20 => CartridgeType::MBC6,
299      0x22 => CartridgeType::MBC7,
300      0xFC => CartridgeType::PocketCamera,
301      0xFD => CartridgeType::Bandai,
302      0xFE => CartridgeType::HuC3,
303      0xFF => CartridgeType::HuC1,
304      _ => panic!("Unknown cartridge for byte {:#x}", byte)
305    }
306  }
307}
308
309impl Debug for CartridgeType {
310  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
311    match self {
312      CartridgeType::MBC => write!(f, "MBC"),
313      CartridgeType::MBC1 => write!(f, "MBC1"),
314      CartridgeType::MBC2 => write!(f, "MBC2"),
315      CartridgeType::MMM01 => write!(f, "MMM01"),
316      CartridgeType::MBC3 => write!(f, "MBC3"),
317      CartridgeType::MBC5 => write!(f, "MBC5"),
318      CartridgeType::MBC6 => write!(f, "MBC6"),
319      CartridgeType::MBC7 => write!(f, "MBC7"),
320      CartridgeType::PocketCamera => write!(f, "Pocket Camera"),
321      CartridgeType::Bandai => write!(f, "Bandai"),
322      CartridgeType::HuC3 => write!(f, "HuC3"),
323      CartridgeType::HuC1 => write!(f, "HuC1")
324    }
325  }
326}
327
328impl Debug for ROMSize {
329  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
330    match self {
331      ROMSize::KB32 => write!(f, "32 kB"),
332      ROMSize::KB64 => write!(f, "64 kB"),
333      ROMSize::KB128 => write!(f, "128 kB"),
334      ROMSize::KB256 => write!(f, "256 kB"),
335      ROMSize::KB512 => write!(f, "512 kB"),
336      ROMSize::MB1 => write!(f, "1 MB"),
337      ROMSize::MB2 => write!(f, "2 MB"),
338      ROMSize::MB4 => write!(f, "4 MB"),
339      ROMSize::MB8 => write!(f, "8 MB")
340    }
341  }
342}
343
344impl ROMSize {
345  pub fn from_byte(byte: u8) -> ROMSize {
346    match byte {
347      0x00 => ROMSize::KB32,
348      0x01 => ROMSize::KB64,
349      0x02 => ROMSize::KB128,
350      0x03 => ROMSize::KB256,
351      0x04 => ROMSize::KB512,
352      0x05 => ROMSize::MB1,
353      0x06 => ROMSize::MB2,
354      0x07 => ROMSize::MB4,
355      0x08 => ROMSize::MB8,
356      _ => panic!("Byte {} does not correspond to any known ROM size", byte)
357    }
358  }
359
360  pub fn bytes(&self) -> usize {
361    match self {
362      ROMSize::KB32 => 0x8000,
363      ROMSize::KB64 => 0x10000,
364      ROMSize::KB128 => 0x20000,
365      ROMSize::KB256 => 0x40000,
366      ROMSize::KB512 => 0x80000,
367      ROMSize::MB1 => 0x100000,
368      ROMSize::MB2 => 0x200000,
369      ROMSize::MB4 => 0x400000,
370      ROMSize::MB8 => 0x800000
371    }
372  }
373}
374
375#[derive(Copy, Clone)]
376pub enum RAMSize {
377  Unavailable,
378  KB8,
379  KB32,
380  KB64,
381  KB128,
382}
383
384impl Debug for RAMSize {
385  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
386    match self {
387      RAMSize::Unavailable => write!(f, "Unavailable"),
388      RAMSize::KB8 => write!(f, "8 kB"),
389      RAMSize::KB32 => write!(f, "32 kB"),
390      RAMSize::KB64 => write!(f, "64 kB"),
391      RAMSize::KB128 => write!(f, "128 kB"),
392    }
393  }
394}
395
396impl RAMSize {
397  pub fn from_byte(byte: u8) -> RAMSize {
398    match byte {
399      0x00 => RAMSize::Unavailable,
400      0x01 => RAMSize::Unavailable,
401      0x02 => RAMSize::KB8,
402      0x03 => RAMSize::KB32,
403      0x04 => RAMSize::KB128,
404      0x05 => RAMSize::KB64,
405      _ => panic!("Byte {} does not correspond to any known RAM size", byte)
406    }
407  }
408
409  pub fn bytes(&self) -> usize {
410    match self {
411      RAMSize::Unavailable => 0,
412      RAMSize::KB8 => 0x8000,
413      RAMSize::KB32 => 0x8000,
414      RAMSize::KB64 => 0x10000,
415      RAMSize::KB128 => 0x20000,
416    }
417  }
418}
419
420#[derive(Copy, Clone, Serialize, Deserialize)]
421pub enum CGBMode {
422  Monochrome,
423  Color,
424  PGB,
425}
426
427impl CGBMode {
428  pub fn from_byte(byte: u8) -> CGBMode {
429    match byte & 0xBF {
430      0x80 => CGBMode::Color,
431      0x82 => CGBMode::PGB,
432      0x84 => CGBMode::PGB,
433      _ => CGBMode::Monochrome
434    }
435  }
436}
437
438impl Debug for CGBMode {
439  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
440    match self {
441      CGBMode::Monochrome => write!(f, "Monochrome"),
442      CGBMode::Color => write!(f, "Color"),
443      CGBMode::PGB => write!(f, "PGB")
444    }
445  }
446}