1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli,Cowering
3 /***********************************************************************************************************
4
5
6 SNES cart emulation
7 (through slot devices)
8
9
10 Carts can be mapped in memory in several different ways and accesses to carts depend
11 on the presence of add-on chips (which map their I/O to diff memory areas)
12
13 Hence, carts can interface with the main system through the following handlers
14 * read_l : typically used to read ROM from memory range [00-7f][0000-ffff]
15 * read_h : typically used to read ROM from memory range [80-ff][0000-ffff]
16 * read_ram : used to read (NV)RAM at the appropriate offset (masks has to be applied
17 *before* calling it, if dealing with >32K RAM)
18 * write_ram : used to write (NV)RAM at the appropriate offset
19 * read_chip : used to read add-on chip registers
20 * write_chip : used to write to add-on chip registers
21
22 Also, we define two additional ROM access handlers, write_l & write_h for carts with
23 subslots (e.g. BS-X compatible ones), that need to write to subslot (NV)RAM independently
24 to accesses to their own (NV)RAM.
25
26 Notes about add-on detection and handling (useful for future addition of st018, cx4, etc.)
27 ===============================================================================================
28 When loading from softlist, m_type would be enough to take care of add-on chips, because
29 the ones needing a CPU dump have it in the zipfile. However, to support these games also
30 from fullpath, both with files having DSP data appended to the .sfc and with older dumps
31 missing DSP data, a second variable is present in the SNES slot: m_addon.
32 From fullpath, support works as follows
33 - get_default_card_software needs to decide whether to use the main devices or the legacy
34 ones containing DSP dump as device roms, so it gets m_type as the main device should be
35 used and if m_addon is ADDON_DSP* or ADDON_ST*, then it checks if the DSP data is appended
36 or if m_type has to be switched to legacy type
37 - call_load needs to detect faulty dumps too, to alloc m_addon_bios and copy the data from
38 the correct place, so if m_addon is ADDON_DSP* or ADDON_ST* it checks whether DSP data is
39 appended or not: if it is, this data is copied to m_addon_bios; if not, then we are in
40 the legacy device case and data is copied from the device rom
41 After the cart has been loaded and emulation has started, only m_type is needed to later
42 handlers installation and cart accesses
43
44 Also notice that, from softlist, DSP1, 1B, 2, 3 are treated as the same device, because they
45 all have the same I/O and the only difference (i.e. the DSP data) comes from the zipfile itself.
46 OTOH, to support faulty dumps missing DSP content, we need separate legacy devices...
47
48
49 ***********************************************************************************************************/
50
51
52 #include "emu.h"
53 #include "snes_slot.h"
54
55 //**************************************************************************
56 // GLOBAL VARIABLES
57 //**************************************************************************
58
59 DEFINE_DEVICE_TYPE(SNS_CART_SLOT, sns_cart_slot_device, "sns_cart_slot", "SNES Cartridge Slot")
60 DEFINE_DEVICE_TYPE(SNS_SUFAMI_CART_SLOT, sns_sufami_cart_slot_device, "sns_sufami_cart_slot", "SNES Sufami Turbo Cartridge Slot")
61 DEFINE_DEVICE_TYPE(SNS_BSX_CART_SLOT, sns_bsx_cart_slot_device, "sns_bsx_cart_slot", "SNES BS-X Cartridge Slot")
62
63 //**************************************************************************
64 // SNES Cartridge Interface
65 //**************************************************************************
66
67 //-------------------------------------------------
68 // device_sns_cart_interface - constructor
69 //-------------------------------------------------
70
device_sns_cart_interface(const machine_config & mconfig,device_t & device)71 device_sns_cart_interface::device_sns_cart_interface(const machine_config &mconfig, device_t &device) :
72 device_interface(device, "snescart"),
73 m_rom(nullptr),
74 m_rom_size(0),
75 m_slot(nullptr)
76 {
77 }
78
79
80 //-------------------------------------------------
81 // ~device_sns_cart_interface - destructor
82 //-------------------------------------------------
83
~device_sns_cart_interface()84 device_sns_cart_interface::~device_sns_cart_interface()
85 {
86 }
87
88 //-------------------------------------------------
89 // rom_alloc - alloc the space for the cart
90 //-------------------------------------------------
91
rom_alloc(uint32_t size,const char * tag)92 void device_sns_cart_interface::rom_alloc(uint32_t size, const char *tag)
93 {
94 if (m_rom == nullptr)
95 {
96 m_rom = device().machine().memory().region_alloc(std::string(tag).append(SNSSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
97 m_rom_size = size;
98 }
99 }
100
101
102 //-------------------------------------------------
103 // nvram_alloc - alloc the space for the nvram
104 //-------------------------------------------------
105
nvram_alloc(uint32_t size)106 void device_sns_cart_interface::nvram_alloc(uint32_t size)
107 {
108 m_nvram.resize(size);
109 }
110
111
112 //-------------------------------------------------
113 // rtc_ram_alloc - alloc the space for the rtc_ram
114 // (needed to save it to NVRAM, will be removed
115 // once the RTCs become devices and NVRAM gets
116 // saved by the device itself)
117 //-------------------------------------------------
118
rtc_ram_alloc(uint32_t size)119 void device_sns_cart_interface::rtc_ram_alloc(uint32_t size)
120 {
121 m_rtc_ram.resize(size);
122 }
123
124
125 //-------------------------------------------------
126 // addon_bios_alloc - alloc the space for the
127 // (optional) add-on CPU bios
128 //-------------------------------------------------
129
addon_bios_alloc(uint32_t size)130 void device_sns_cart_interface::addon_bios_alloc(uint32_t size)
131 {
132 m_bios.resize(size);
133 }
134
135
136 //-------------------------------------------------
137 // rom_map_setup - setup map of rom banks in 32K
138 // blocks, so to simplify ROM access
139 //-------------------------------------------------
140
rom_map_setup(uint32_t size)141 void device_sns_cart_interface::rom_map_setup(uint32_t size)
142 {
143 int i;
144 // setup the rom_bank_map array to faster ROM read
145 for (i = 0; i < size / 0x8000; i++)
146 rom_bank_map[i] = i;
147
148 // fill up remaining blocks with mirrors
149 while (i % 256)
150 {
151 int j = 0, repeat_banks;
152 while ((i % (256 >> j)) && j < 8)
153 j++;
154 repeat_banks = i % (256 >> (j - 1));
155 for (int k = 0; k < repeat_banks; k++)
156 rom_bank_map[i + k] = rom_bank_map[i + k - repeat_banks];
157 i += repeat_banks;
158 }
159
160 // check bank map!
161 // for (i = 0; i < 256; i++)
162 // {
163 // printf("bank %3d = %3d\t", i, rom_bank_map[i]);
164 // if ((i%8) == 7)
165 // printf("\n");
166 // }
167 }
168
169
170 //-------------------------------------------------
171 // write_irq - set the cart IRQ output
172 //-------------------------------------------------
173
WRITE_LINE_MEMBER(device_sns_cart_interface::write_irq)174 WRITE_LINE_MEMBER(device_sns_cart_interface::write_irq)
175 {
176 if (m_slot != nullptr)
177 m_slot->write_irq(state);
178 }
179
180 //-------------------------------------------------
181 // read_open_bus - read from the open bus
182 //-------------------------------------------------
183
read_open_bus()184 uint8_t device_sns_cart_interface::read_open_bus()
185 {
186 if (m_slot != nullptr)
187 return m_slot->read_open_bus();
188
189 return 0xff;
190 }
191
192 //**************************************************************************
193 // LIVE DEVICE
194 //**************************************************************************
195
196 //-------------------------------------------------
197 // base_sns_cart_slot_device - constructor
198 //-------------------------------------------------
base_sns_cart_slot_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)199 base_sns_cart_slot_device::base_sns_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
200 device_t(mconfig, type, tag, owner, clock),
201 device_image_interface(mconfig, *this),
202 device_slot_interface(mconfig, *this),
203 m_addon(ADDON_NONE),
204 m_type(SNES_MODE20),
205 m_cart(nullptr),
206 m_irq_callback(*this),
207 m_open_bus_callback(*this)
208 {
209 }
210
sns_cart_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)211 sns_cart_slot_device::sns_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
212 base_sns_cart_slot_device(mconfig, SNS_CART_SLOT, tag, owner, clock)
213 {
214 }
215
sns_sufami_cart_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)216 sns_sufami_cart_slot_device::sns_sufami_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
217 base_sns_cart_slot_device(mconfig, SNS_SUFAMI_CART_SLOT, tag, owner, clock)
218 {
219 }
220
sns_bsx_cart_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)221 sns_bsx_cart_slot_device::sns_bsx_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
222 base_sns_cart_slot_device(mconfig, SNS_BSX_CART_SLOT, tag, owner, clock)
223 {
224 }
225
226 //-------------------------------------------------
227 // base_sns_cart_slot_device - destructor
228 //-------------------------------------------------
229
~base_sns_cart_slot_device()230 base_sns_cart_slot_device::~base_sns_cart_slot_device()
231 {
232 }
233
234 //-------------------------------------------------
235 // device_start - device-specific startup
236 //-------------------------------------------------
237
device_start()238 void base_sns_cart_slot_device::device_start()
239 {
240 m_cart = dynamic_cast<device_sns_cart_interface *>(get_card_device());
241 if (m_cart != nullptr)
242 m_cart->m_slot = this;
243
244 m_irq_callback.resolve_safe();
245 m_open_bus_callback.resolve_safe(0xff);
246 }
247
248
249 //-------------------------------------------------
250 // SNES PCB
251 //-------------------------------------------------
252
253
254 struct sns_slot
255 {
256 int pcb_id;
257 const char *slot_option;
258 };
259
260 // Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
261 static const sns_slot slot_list[] =
262 {
263 { SNES_MODE20, "lorom"},
264 { SNES_BSXLO, "lorom_bsx"},
265 { SNES_CX4, "lorom_cx4"},
266 { SNES_DSP, "lorom_dsp"},
267 { SNES_DSP4, "lorom_dsp4"},
268 { SNES_OBC1, "lorom_obc1"},
269 { SNES_SA1, "lorom_sa1"},
270 { SNES_SDD1, "lorom_sdd1"},
271 { SNES_GSU1, "lorom_gsu1"},
272 { SNES_GSU2, "lorom_gsu2"},
273 { SNES_Z80GB, "lorom_sgb"},
274 { SNES_ST010, "lorom_st010"},
275 { SNES_ST011, "lorom_st011"},
276 { SNES_ST018, "lorom_st018"},
277 { SNES_SUFAMITURBO, "lorom_sufami"},
278 { SNES_MODE21, "hirom"},
279 { SNES_DSP_MODE21, "hirom_dsp"},
280 { SNES_BSXHI, "hirom_bsx"},
281 { SNES_SPC7110, "hirom_spc7110"},
282 { SNES_SPC7110_RTC, "hirom_spcrtc"},
283 { SNES_SRTC, "hirom_srtc"},
284 { SNES_BSX, "bsxrom"},
285 // BS-X memory packs
286 { SNES_BSMEMPAK, "bsmempak"},
287 // Sufami Turbo carts
288 { SNES_STROM, "strom"},
289 // Event carts
290 { SNES_PFEST94, "pfest94" },
291 // pirate carts
292 { SNES_POKEMON, "lorom_poke"},
293 { SNES_TEKKEN2, "lorom_tekken2"},
294 { SNES_SOULBLAD, "lorom_sbld"},
295 { SNES_MCPIR1, "lorom_mcpir1"},
296 { SNES_MCPIR2, "lorom_mcpir2"},
297 { SNES_20COL, "lorom_20col"},
298 { SNES_BANANA, "lorom_pija"}, // wip
299 { SNES_BUGS, "lorom_bugs"}, // wip
300 // legacy slots to support DSPx games from fullpath
301 { SNES_DSP1_LEG, "lorom_dsp1leg"},
302 { SNES_DSP1B_LEG, "lorom_dsp1bleg"},
303 { SNES_DSP2_LEG, "lorom_dsp2leg"},
304 { SNES_DSP3_LEG, "lorom_dsp3leg"},
305 { SNES_DSP4_LEG, "lorom_dsp4leg"},
306 { SNES_DSP1_MODE21_LEG, "hirom_dsp1leg"},
307 { SNES_ST010_LEG, "lorom_st10leg"},
308 { SNES_ST011_LEG, "lorom_st11leg"}
309 };
310
sns_get_pcb_id(const char * slot)311 static int sns_get_pcb_id(const char *slot)
312 {
313 for (auto & elem : slot_list)
314 {
315 if (!core_stricmp(elem.slot_option, slot))
316 return elem.pcb_id;
317 }
318
319 return 0;
320 }
321
sns_get_slot(int type)322 static const char *sns_get_slot(int type)
323 {
324 for (auto & elem : slot_list)
325 {
326 if (elem.pcb_id == type)
327 return elem.slot_option;
328 }
329
330 return "lorom";
331 }
332
333
334 /*-------------------------------------------------
335 SRAM handling
336 -------------------------------------------------*/
337
338 /*************************************
339 * Helper functions
340 *************************************/
341
342
343 /* Here we add a couple of cart utilities, to avoid duplicating the code in each DEVICE_IMAGE_LOAD */
snes_skip_header(const uint8_t * ROM,uint32_t rom_size) const344 uint32_t base_sns_cart_slot_device::snes_skip_header(const uint8_t *ROM, uint32_t rom_size) const
345 {
346 uint8_t header[512];
347 uint32_t offset = 512;
348
349 /* Check for a header (512 bytes) */
350 memcpy(header, ROM, 512);
351
352 if ((header[8] == 0xaa) && (header[9] == 0xbb) && (header[10] == 0x04))
353 {
354 /* Found an SWC identifier */
355 logerror("Found header (SWC) - Skipped\n");
356 }
357 else if ((header[0] | (header[1] << 8)) == (((rom_size - 512) / 1024) / 8))
358 {
359 /* Some headers have the rom size at the start, if this matches with the actual rom size, we probably have a header */
360 logerror("Found header (size) - Skipped\n");
361 }
362 else if ((rom_size % 0x8000) == 512)
363 {
364 /* As a last check we'll see if there's exactly 512 bytes extra to this image. */
365 logerror("Found header (extra) - Skipped\n");
366 }
367 else
368 {
369 /* No header found so go back to the start of the file */
370 logerror("No header found.\n");
371 offset = 0;
372 }
373
374 return offset;
375 }
376
377
378 /* This function assign a 'score' to data immediately after 'offset' to measure how valid they are
379 as information block (to decide if the image is HiRom, LoRom, ExLoRom or ExHiRom) */
380 /* Code from bsnes, courtesy of byuu - http://byuu.org/ , based on previous code by Cowering */
snes_validate_infoblock(const uint8_t * infoblock,uint32_t offset)381 static int snes_validate_infoblock(const uint8_t *infoblock, uint32_t offset)
382 {
383 int score = 0;
384 uint16_t reset_vector = infoblock[offset + 0x3c] | (infoblock[offset + 0x3d] << 8);
385 uint16_t checksum = infoblock[offset + 0x1e] | (infoblock[offset + 0x1f] << 8);
386 uint16_t ichecksum = infoblock[offset + 0x1c] | (infoblock[offset + 0x1d] << 8);
387 uint8_t reset_opcode = infoblock[(offset & ~0x7fff) | (reset_vector & 0x7fff)]; //first opcode executed upon reset
388 uint8_t mapper = infoblock[offset + 0x15] & ~0x10; //mask off irrelevant FastROM-capable bit
389
390 /* $00:[000-7fff] contains uninitialized RAM and MMIO.
391 reset vector must point to ROM at $00:[8000-ffff] to be considered valid. */
392 if (reset_vector < 0x8000)
393 return 0;
394
395 /* some images duplicate the header in multiple locations, and others have completely
396 invalid header information that cannot be relied upon. The code below will analyze
397 the first opcode executed at the specified reset vector to determine the probability
398 that this is the correct header. Score is assigned accordingly. */
399
400 /* most likely opcodes */
401 if (reset_opcode == 0x78 //sei
402 || reset_opcode == 0x18 //clc (clc; xce)
403 || reset_opcode == 0x38 //sec (sec; xce)
404 || reset_opcode == 0x9c //stz $nnnn (stz $4200)
405 || reset_opcode == 0x4c //jmp $nnnn
406 || reset_opcode == 0x5c //jml $nnnnnn
407 )
408 score += 8;
409
410 /* plausible opcodes */
411 if (reset_opcode == 0xc2 //rep #$nn
412 || reset_opcode == 0xe2 //sep #$nn
413 || reset_opcode == 0xad //lda $nnnn
414 || reset_opcode == 0xae //ldx $nnnn
415 || reset_opcode == 0xac //ldy $nnnn
416 || reset_opcode == 0xaf //lda $nnnnnn
417 || reset_opcode == 0xa9 //lda #$nn
418 || reset_opcode == 0xa2 //ldx #$nn
419 || reset_opcode == 0xa0 //ldy #$nn
420 || reset_opcode == 0x20 //jsr $nnnn
421 || reset_opcode == 0x22 //jsl $nnnnnn
422 )
423 score += 4;
424
425 /* implausible opcodes */
426 if (reset_opcode == 0x40 //rti
427 || reset_opcode == 0x60 //rts
428 || reset_opcode == 0x6b //rtl
429 || reset_opcode == 0xcd //cmp $nnnn
430 || reset_opcode == 0xec //cpx $nnnn
431 || reset_opcode == 0xcc //cpy $nnnn
432 )
433 score -= 4;
434
435 /* least likely opcodes */
436 if (reset_opcode == 0x00 //brk #$nn
437 || reset_opcode == 0x02 //cop #$nn
438 || reset_opcode == 0xdb //stp
439 || reset_opcode == 0x42 //wdm
440 || reset_opcode == 0xff //sbc $nnnnnn,x
441 )
442 score -= 8;
443
444 /* Sometimes, both the header and reset vector's first opcode will match ...
445 fallback and rely on info validity in these cases to determine more likely header. */
446
447 /* a valid checksum is the biggest indicator of a valid header. */
448 if ((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0))
449 score += 4;
450
451 /* then there are the expected mapper values */
452 if (offset == 0x007fc0 && mapper == 0x20) // 0x20 is usually LoROM
453 score += 2;
454
455 if (offset == 0x00ffc0 && mapper == 0x21) // 0x21 is usually HiROM
456 score += 2;
457
458 if (offset == 0x007fc0 && mapper == 0x22) // 0x22 is usually ExLoROM
459 score += 2;
460
461 if (offset == 0x40ffc0 && mapper == 0x25) // 0x25 is usually ExHiROM
462 score += 2;
463
464 /* finally, there are valid values in the Company, Region etc. fields */
465 if (infoblock[offset + 0x1a] == 0x33) // Company field: 0x33 indicates extended header
466 score += 2;
467
468 if (infoblock[offset + 0x16] < 0x08) // ROM Type field
469 score++;
470
471 if (infoblock[offset + 0x17] < 0x10) // ROM Size field
472 score++;
473
474 if (infoblock[offset + 0x18] < 0x08) // SRAM Size field
475 score++;
476
477 if (infoblock[offset + 0x19] < 14) // Region field
478 score++;
479
480 /* do we still have a positive score? */
481 if (score < 0)
482 score = 0;
483
484 return score;
485 }
486
487 /* This determines if a cart is in Mode 20, 21, 22 or 25; sets state->m_cart[0].mode and
488 state->m_cart[0].sram accordingly; and returns the offset of the internal header (needed to
489 detect BSX and ST carts) */
snes_find_hilo_mode(const device_t * device,const uint8_t * buffer,uint32_t buf_len)490 static uint32_t snes_find_hilo_mode(const device_t *device, const uint8_t *buffer, uint32_t buf_len)
491 {
492 uint8_t valid_mode20 = 0;
493 uint8_t valid_mode21 = 0;
494 uint8_t valid_mode25 = 0;
495 uint32_t retvalue;
496
497 /* Now to determine if this is a lo-ROM, a hi-ROM or an extended lo/hi-ROM */
498 if (buf_len > 0x007fc0)
499 valid_mode20 = snes_validate_infoblock(buffer, 0x007fc0);
500 if (buf_len > 0x00ffc0)
501 valid_mode21 = snes_validate_infoblock(buffer, 0x00ffc0);
502 if (buf_len > 0x40ffc0)
503 valid_mode25 = snes_validate_infoblock(buffer, 0x40ffc0);
504
505 /* Images larger than 32mbits are likely ExHiRom */
506 if (valid_mode25)
507 valid_mode25 += 4;
508
509 if ((valid_mode20 >= valid_mode21) && (valid_mode20 >= valid_mode25))
510 retvalue = 0x007fc0;
511 else if (valid_mode21 >= valid_mode25)
512 retvalue = 0x00ffc0;
513 else
514 retvalue = 0x40ffc0;
515
516 device->logerror( "\t HiROM/LoROM id: %s (LoROM: %d , HiROM: %d, ExHiROM: %d)\n",
517 (retvalue == 0x007fc0) ? "LoROM" :
518 (retvalue == 0x00ffc0) ? "HiROM" :
519 (retvalue == 0x40ffc0) ? "ExHiROM" : "Other",
520 valid_mode20, valid_mode21, valid_mode25);
521
522 return retvalue;
523 }
524
525
snes_find_addon_chip(const uint8_t * buffer,uint32_t start_offs,uint32_t len)526 static int snes_find_addon_chip(const uint8_t *buffer, uint32_t start_offs, uint32_t len)
527 {
528 /* Info mostly taken from http://black-ship.net/~tukuyomi/snesemu/misc/hardware/-from%20nsrt.edgeemu.com-chipinfo.htm */
529 switch (buffer[start_offs + 0x16])
530 {
531 case 0x00:
532 case 0x01:
533 case 0x02:
534 break;
535
536 case 0x03:
537 if (buffer[start_offs + 0x15] == 0x30)
538 return ADDON_DSP4;
539 else
540 return ADDON_DSP1;
541
542 case 0x04:
543 return ADDON_DSP1;
544
545 case 0x05:
546 // DSP2 can be detected by (buffer[start_offs + 0x15] == 0x20)
547 // DSP3 is harder to detect, and one has to rely on the manufacturer (Bandai)
548 // by checking (buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2)
549 // in other cases is DSP1, but we do treat all these together...
550 if (buffer[start_offs + 0x15] == 0x20)
551 return ADDON_DSP2;
552 else if ((buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2))
553 return ADDON_DSP3;
554 else
555 return ADDON_DSP1;
556
557 case 0x13: // Mario Chip 1
558 case 0x14: // GSU-x
559 case 0x15: // GSU-x
560 case 0x1a: // GSU-1 (21 MHz at start)
561 if (buffer[start_offs + 0x15] == 0x20)
562 {
563 if (len > 1048576)
564 return ADDON_GSU2;
565 else
566 return ADDON_GSU1;
567 }
568 break;
569
570 case 0x25:
571 return ADDON_OBC1;
572
573 case 0x32: // needed by a Sample game (according to ZSNES)
574 case 0x34:
575 case 0x35:
576 if (buffer[start_offs + 0x15] == 0x23)
577 return ADDON_SA1;
578 break;
579
580 case 0x43:
581 case 0x45:
582 if (buffer[start_offs + 0x15] == 0x32)
583 return ADDON_SDD1;
584 break;
585
586 case 0x55:
587 if (buffer[start_offs + 0x15] == 0x35)
588 return ADDON_SRTC;
589 break;
590
591 case 0xe3:
592 return ADDON_Z80GB;
593
594 case 0xf3:
595 return ADDON_CX4;
596
597 case 0xf5:
598 if (buffer[start_offs + 0x15] == 0x30)
599 return ADDON_ST018;
600 else if (buffer[start_offs + 0x15] == 0x3a)
601 return ADDON_SPC7110;
602 break;
603
604 case 0xf6:
605 /* These Seta ST-01X chips have both 0x30 at 0xffd5,
606 they only differ for the 'size' at 0xffd7 */
607 if (buffer[start_offs + 0x17] < 0x0a)
608 return ADDON_ST011;
609 else
610 return ADDON_ST010;
611
612 case 0xf9:
613 if (buffer[start_offs + 0x15] == 0x3a)
614 return ADDON_SPC7110_RTC;
615 break;
616
617 default:
618 break;
619 }
620 return -1;
621 }
622
623
624 /*-------------------------------------------------
625 call load
626 -------------------------------------------------*/
627
628
call_load()629 image_init_result base_sns_cart_slot_device::call_load()
630 {
631 if (m_cart)
632 {
633 uint8_t *ROM;
634 uint32_t len, offset = 0;
635 const char *slot_name;
636
637 /* Check for a header (512 bytes), and skip it if found */
638 if (!loaded_through_softlist())
639 {
640 uint32_t tmplen = length();
641 std::vector<uint8_t> tmpROM(tmplen);
642 fread(&tmpROM[0], tmplen);
643 offset = snes_skip_header(&tmpROM[0], tmplen);
644 fseek(offset, SEEK_SET);
645 }
646
647 len = !loaded_through_softlist() ? (length() - offset) : get_software_region_length("rom");
648
649 m_cart->rom_alloc(len, tag());
650 ROM = m_cart->get_rom_base();
651 if (!loaded_through_softlist())
652 fread(ROM, len);
653 else
654 memcpy(ROM, get_software_region("rom"), len);
655
656 m_cart->rom_map_setup(len);
657
658 // check for on-cart CPU bios
659 if (loaded_through_softlist())
660 {
661 if (get_software_region("addon"))
662 {
663 m_cart->addon_bios_alloc(get_software_region_length("addon"));
664 memcpy(m_cart->get_addon_bios_base(), get_software_region("addon"), get_software_region_length("addon"));
665 }
666 }
667
668 // get pcb type
669 if (!loaded_through_softlist())
670 get_cart_type_addon(ROM, len, m_type, m_addon);
671 else
672 {
673 if ((slot_name = get_feature("slot")) == nullptr)
674 m_type = SNES_MODE20;
675 else
676 m_type = sns_get_pcb_id(slot_name);
677
678 if (m_type == SNES_DSP && len > 0x100000)
679 m_type = SNES_DSP_2MB;
680 }
681
682 if (!loaded_through_softlist())
683 setup_addon_from_fullpath();
684
685 // in carts with an add-on CPU having internal dump, this speeds up access to the internal rom
686 // by installing read_bank in address space and mapping m_bios there
687 m_cart->speedup_addon_bios_access();
688
689 setup_nvram();
690
691 if (m_cart->get_nvram_size() || m_cart->get_rtc_ram_size())
692 {
693 uint32_t tot_size = m_cart->get_nvram_size() + m_cart->get_rtc_ram_size();
694 std::vector<uint8_t> temp_nvram(tot_size);
695 battery_load(&temp_nvram[0], tot_size, 0xff);
696 if (m_cart->get_nvram_size())
697 memcpy(m_cart->get_nvram_base(), &temp_nvram[0], m_cart->get_nvram_size());
698 if (m_cart->get_rtc_ram_size())
699 memcpy(m_cart->get_rtc_ram_base(), &temp_nvram[m_cart->get_nvram_size()], m_cart->get_rtc_ram_size());
700 }
701
702 //printf("Type %d\n", m_type);
703
704 internal_header_logging(ROM, len);
705
706 return image_init_result::PASS;
707 }
708
709 return image_init_result::PASS;
710 }
711
712
713 /*-------------------------------------------------
714 call_unload
715 -------------------------------------------------*/
716
call_unload()717 void base_sns_cart_slot_device::call_unload()
718 {
719 if (m_cart)
720 {
721 if (m_cart->get_nvram_size() || m_cart->get_rtc_ram_size())
722 {
723 uint32_t tot_size = m_cart->get_nvram_size() + m_cart->get_rtc_ram_size();
724 std::vector<uint8_t> temp_nvram(tot_size);
725 if (m_cart->get_nvram_size())
726 memcpy(&temp_nvram[0], m_cart->get_nvram_base(), m_cart->get_nvram_size());
727 if (m_cart->get_rtc_ram_size())
728 memcpy(&temp_nvram[m_cart->get_nvram_size()], m_cart->get_rtc_ram_base(), m_cart->get_rtc_ram_size());
729
730 battery_save(&temp_nvram[0], tot_size);
731 }
732 }
733 }
734
735
setup_addon_from_fullpath()736 void base_sns_cart_slot_device::setup_addon_from_fullpath()
737 {
738 // if we already have an add-on bios or if no addon has been detected, we have nothing to do
739 if (m_cart->get_addon_bios_size() || m_addon == ADDON_NONE)
740 return;
741
742 // check if the add-on dump is appended to the file
743 // if this is the case, copy it in m_bios and refresh
744 // the rom_bank_map with correct game rom size
745 switch (m_addon)
746 {
747 case ADDON_DSP1:
748 case ADDON_DSP1B:
749 case ADDON_DSP2:
750 case ADDON_DSP3:
751 case ADDON_DSP4:
752 // check for add-on dump
753 if ((m_cart->get_rom_size() & 0x7fff) == 0x2800)
754 {
755 logerror("Found NEC DSP dump at the bottom of the ROM.\n");
756 m_cart->addon_bios_alloc(0x2800);
757 memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2800), 0x2800);
758 m_cart->rom_map_setup(m_cart->get_rom_size() - 0x2800);
759 }
760 // check for byuu's compressed version (swapped order of bytes and stripped fixed 0x00 bytes)
761 if ((m_cart->get_rom_size() & 0x7fff) == 0x2000)
762 {
763 logerror("Found NEC DSP dump (byuu's version) at the bottom of the ROM.\n");
764 m_cart->addon_bios_alloc(0x2800);
765 for (int i = 0; i < 0x800; i++)
766 {
767 memcpy(m_cart->get_addon_bios_base() + i * 4 + 2, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 0, 1);
768 memcpy(m_cart->get_addon_bios_base() + i * 4 + 1, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 1, 1);
769 memcpy(m_cart->get_addon_bios_base() + i * 4 + 0, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x2000) + i * 3 + 2, 1);
770 memset(m_cart->get_addon_bios_base() + i * 4 + 3, 0xff, 1);
771 }
772 memcpy(m_cart->get_addon_bios_base() + 0x2000, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x1800), 0x800);
773 m_cart->rom_map_setup(m_cart->get_rom_size() - 0x2000);
774 }
775 break;
776 case ADDON_ST010:
777 case ADDON_ST011:
778 // check for add-on dump
779 if ((m_cart->get_rom_size() & 0x3ffff) == 0x11000)
780 {
781 logerror("Found Seta DSP dump at the bottom of the ROM.\n");
782 m_cart->addon_bios_alloc(0x11000);
783 memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x11000), 0x11000);
784 m_cart->rom_map_setup(m_cart->get_rom_size() - 0x11000);
785 }
786 // check for byuu's compressed version (swapped order of bytes and stripped fixed 0x00 bytes)
787 if ((m_cart->get_rom_size() & 0xffff) == 0xd000)
788 {
789 logerror("Found Seta DSP dump (byuu's version) at the bottom of the ROM.\n");
790 m_cart->addon_bios_alloc(0x11000);
791 for (int i = 0; i < 0x4000; i++)
792 {
793 memcpy(m_cart->get_addon_bios_base() + i * 4 + 2, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 0, 1);
794 memcpy(m_cart->get_addon_bios_base() + i * 4 + 1, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 1, 1);
795 memcpy(m_cart->get_addon_bios_base() + i * 4 + 0, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xd000) + i * 3 + 2, 1);
796 memset(m_cart->get_addon_bios_base() + i * 4 + 3, 0xff, 1);
797 }
798 memcpy(m_cart->get_addon_bios_base() + 0x10000, m_cart->get_rom_base() + (m_cart->get_rom_size() - 0xc000), 0x1000);
799 m_cart->rom_map_setup(m_cart->get_rom_size() - 0xd000);
800 }
801 break;
802 case ADDON_CX4:
803 if ((m_cart->get_rom_size() & 0x7fff) == 0x0c00)
804 {
805 logerror("Found CX4 dump at the bottom of the ROM.\n");
806 m_cart->addon_bios_alloc(0x0c00);
807 memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x0c00), 0x0c00);
808 m_cart->rom_map_setup(m_cart->get_rom_size() - 0x0c00);
809 }
810 break;
811 case ADDON_ST018:
812 if ((m_cart->get_rom_size() & 0x3ffff) == 0x28000)
813 {
814 logerror("Found ST018 dump at the bottom of the ROM.\n");
815 m_cart->addon_bios_alloc(0x28000);
816 memcpy(m_cart->get_addon_bios_base(), m_cart->get_rom_base() + (m_cart->get_rom_size() - 0x28000), 0x28000);
817 m_cart->rom_map_setup(m_cart->get_rom_size() - 0x28000);
818 }
819 break;
820 }
821
822 // otherwise, we need to use the legacy versions including DSP dump in device romset
823 if (!m_cart->get_addon_bios_size())
824 {
825 std::string region = std::string(m_cart->device().tag()).append(":addon");
826 uint8_t *ROM;
827
828 switch (m_addon)
829 {
830 case ADDON_DSP1:
831 ROM = machine().root_device().memregion(region.c_str())->base();
832 m_cart->addon_bios_alloc(0x2800);
833 memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
834 break;
835 case ADDON_DSP1B:
836 ROM = machine().root_device().memregion(region.c_str())->base();
837 m_cart->addon_bios_alloc(0x2800);
838 memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
839 break;
840 case ADDON_DSP2:
841 ROM = machine().root_device().memregion(region.c_str())->base();
842 m_cart->addon_bios_alloc(0x2800);
843 memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
844 break;
845 case ADDON_DSP3:
846 ROM = machine().root_device().memregion(region.c_str())->base();
847 m_cart->addon_bios_alloc(0x2800);
848 memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
849 break;
850 case ADDON_DSP4:
851 ROM = machine().root_device().memregion(region.c_str())->base();
852 m_cart->addon_bios_alloc(0x2800);
853 memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
854 break;
855 case ADDON_ST010:
856 ROM = machine().root_device().memregion(region.c_str())->base();
857 m_cart->addon_bios_alloc(0x11000);
858 memcpy(m_cart->get_addon_bios_base(), ROM, 0x11000);
859 break;
860 case ADDON_ST011:
861 ROM = machine().root_device().memregion(region.c_str())->base();
862 m_cart->addon_bios_alloc(0x11000);
863 memcpy(m_cart->get_addon_bios_base(), ROM, 0x11000);
864 break;
865 }
866 }
867
868 }
869
setup_nvram()870 void base_sns_cart_slot_device::setup_nvram()
871 {
872 uint8_t *ROM = (uint8_t *)m_cart->get_rom_base();
873 uint32_t size = 0;
874 if (!loaded_through_softlist())
875 {
876 int hilo_mode = snes_find_hilo_mode(this, ROM, m_cart->get_rom_size());
877 uint8_t sram_size = (m_type == SNES_GSU1 || m_type == SNES_GSU2) ? (ROM[0x00ffbd] & 0x07) : (ROM[hilo_mode + 0x18] & 0x07);
878 if (sram_size)
879 {
880 uint32_t max = (hilo_mode == 0x007fc0) ? 0x80000 : 0x20000; // MODE20 vs MODE21
881 size = 1024 << sram_size;
882 if (size > max)
883 size = max;
884 }
885 }
886 else
887 {
888 if (get_software_region("nvram"))
889 size = get_software_region_length("nvram");
890 }
891
892 if (size)
893 m_cart->nvram_alloc(size);
894
895 if (m_type == SNES_STROM)
896 m_cart->nvram_alloc(0x20000);
897 if (m_type == SNES_BSX)
898 m_cart->nvram_alloc(0x8000);
899
900 // setup also RTC SRAM, when needed (to be removed when RTCs are converted to devices)
901 if (m_type == SNES_SRTC)
902 m_cart->rtc_ram_alloc(13);
903 if (m_type == SNES_SPC7110_RTC)
904 m_cart->rtc_ram_alloc(16);
905 }
906
907
908
get_cart_type_addon(const uint8_t * ROM,uint32_t len,int & type,int & addon) const909 void base_sns_cart_slot_device::get_cart_type_addon(const uint8_t *ROM, uint32_t len, int &type, int &addon) const
910 {
911 // First, look if the cart is HiROM or LoROM (and set snes_cart accordingly)
912 int hilo_mode = snes_find_hilo_mode(this, ROM, len);
913
914 switch (hilo_mode)
915 {
916 case 0x007fc0: // LoRom & ExLoRom
917 type = SNES_MODE20;
918 break;
919 case 0x00ffc0: // HiRom
920 case 0x40ffc0: // ExHiRom
921 type = SNES_MODE21;
922 break;
923 default:
924 break;
925 }
926
927 // detect Sufami Turbo...
928 if (type == SNES_MODE20 && !memcmp(ROM, "BANDAI SFC-ADX", 14))
929 {
930 if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
931 type = SNES_SUFAMITURBO;
932 else
933 type = SNES_STROM;
934 }
935
936 // detect BS-X Base Cart
937 if (!memcmp(ROM + hilo_mode, "Satellaview BS-X ", 21))
938 type = SNES_BSX;
939 // Detect BS-X Flash Cart
940 if ((ROM[hilo_mode + 0x13] == 0x00 || ROM[hilo_mode + 0x13] == 0xff) && ROM[hilo_mode + 0x14] == 0x00)
941 {
942 uint8_t n15 = ROM[hilo_mode + 0x15];
943 if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
944 {
945 if (ROM[hilo_mode + 0x1a] == 0x33 || ROM[hilo_mode + 0x1a] == 0xff)
946 type = SNES_BSMEMPAK;
947 }
948 }
949
950 // check for add-on chips...
951 if (len >= hilo_mode + 0x1a)
952 {
953 addon = snes_find_addon_chip(ROM, hilo_mode, len);
954 if (addon != -1)
955 {
956 // m_type handles DSP1,2,3 in the same way, but snes_add requires them to be separate...
957 switch (addon)
958 {
959 case ADDON_CX4:
960 type = SNES_CX4;
961 break;
962 case ADDON_DSP1:
963 case ADDON_DSP1B:
964 case ADDON_DSP2:
965 case ADDON_DSP3:
966 if (type == SNES_MODE20 && len > 0x100000)
967 type = SNES_DSP_2MB;
968 else if (type == SNES_MODE21)
969 type = SNES_DSP_MODE21;
970 else
971 type = SNES_DSP;
972 break;
973 case ADDON_DSP4:
974 type = SNES_DSP4;
975 break;
976 case ADDON_OBC1:
977 type = SNES_OBC1;
978 break;
979 case ADDON_SA1:
980 type = SNES_SA1;
981 break;
982 case ADDON_SDD1:
983 type = SNES_SDD1;
984 break;
985 case ADDON_GSU1:
986 type = SNES_GSU1;
987 break;
988 case ADDON_GSU2:
989 type = SNES_GSU2;
990 break;
991 case ADDON_SPC7110:
992 type = SNES_SPC7110;
993 break;
994 case ADDON_SPC7110_RTC:
995 type = SNES_SPC7110_RTC;
996 break;
997 case ADDON_ST010:
998 type = SNES_ST010;
999 break;
1000 case ADDON_ST011:
1001 type = SNES_ST011;
1002 break;
1003 case ADDON_ST018:
1004 type = SNES_ST018;
1005 break;
1006 case ADDON_SRTC:
1007 type = SNES_SRTC;
1008 break;
1009 case ADDON_Z80GB:
1010 type = SNES_Z80GB;
1011 break;
1012 }
1013 }
1014 }
1015 }
1016
1017 /*-------------------------------------------------
1018 get default card software
1019 -------------------------------------------------*/
1020
get_default_card_software(get_default_card_software_hook & hook) const1021 std::string base_sns_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
1022 {
1023 if (hook.image_file())
1024 {
1025 const char *slot_string;
1026 uint32_t offset;
1027 uint32_t len = hook.image_file()->size();
1028 std::vector<uint8_t> rom(len);
1029 int type = 0, addon = 0;
1030
1031 hook.image_file()->read(&rom[0], len);
1032
1033 offset = snes_skip_header(&rom[0], len);
1034
1035 get_cart_type_addon(&rom[offset], len - offset, type, addon);
1036 // here we're from fullpath, so check if it's a DSP game which needs legacy device (i.e. it has no appended DSP dump)
1037 switch (addon)
1038 {
1039 case ADDON_DSP1:
1040 if ((len & 0x7fff) != 0x2800 && (len & 0x7fff) != 0x2000)
1041 {
1042 if (type == SNES_DSP_MODE21)
1043 type = SNES_DSP1_MODE21_LEG;
1044 else
1045 type = SNES_DSP1_LEG;
1046 }
1047 break;
1048 case ADDON_DSP1B:
1049 if ((len & 0x7fff) != 0x2800 && (len & 0x7fff) != 0x2000)
1050 type = SNES_DSP1B_LEG;
1051 break;
1052 case ADDON_DSP2:
1053 if ((len & 0x7fff) != 0x2800 && (len & 0x7fff) != 0x2000)
1054 type = SNES_DSP2_LEG;
1055 break;
1056 case ADDON_DSP3:
1057 if ((len & 0x7fff) != 0x2800 && (len & 0x7fff) != 0x2000)
1058 type = SNES_DSP3_LEG;
1059 break;
1060 case ADDON_DSP4:
1061 if ((len & 0x7fff) != 0x2800 && (len & 0x7fff) != 0x2000)
1062 type = SNES_DSP4_LEG;
1063 break;
1064 case ADDON_ST010:
1065 if ((len & 0x3ffff) != 0x11000 && (len & 0xffff) != 0xd000)
1066 type = SNES_ST010_LEG;
1067 break;
1068 case ADDON_ST011:
1069 if ((len & 0x3ffff) != 0x11000 && (len & 0xffff) != 0xd000)
1070 type = SNES_ST011_LEG;
1071 break;
1072 }
1073
1074 slot_string = sns_get_slot(type);
1075
1076 return std::string(slot_string);
1077 }
1078
1079 return software_get_default_slot("lorom");
1080 }
1081
1082
1083 /*-------------------------------------------------
1084 read
1085 -------------------------------------------------*/
1086
read_l(offs_t offset)1087 uint8_t base_sns_cart_slot_device::read_l(offs_t offset)
1088 {
1089 if (m_cart)
1090 return m_cart->read_l(offset);
1091 else
1092 return 0xff;
1093 }
1094
read_h(offs_t offset)1095 uint8_t base_sns_cart_slot_device::read_h(offs_t offset)
1096 {
1097 if (m_cart)
1098 return m_cart->read_h(offset);
1099 else
1100 return 0xff;
1101 }
1102
read_ram(offs_t offset)1103 uint8_t base_sns_cart_slot_device::read_ram(offs_t offset)
1104 {
1105 if (m_cart)
1106 return m_cart->read_ram(offset);
1107 else
1108 return 0xff;
1109 }
1110
chip_read(offs_t offset)1111 uint8_t base_sns_cart_slot_device::chip_read(offs_t offset)
1112 {
1113 if (m_cart)
1114 return m_cart->chip_read(offset);
1115 else
1116 return 0xff;
1117 }
1118
1119 /*-------------------------------------------------
1120 write
1121 -------------------------------------------------*/
1122
write_l(offs_t offset,uint8_t data)1123 void base_sns_cart_slot_device::write_l(offs_t offset, uint8_t data)
1124 {
1125 if (m_cart)
1126 m_cart->write_l(offset, data);
1127 }
1128
write_h(offs_t offset,uint8_t data)1129 void base_sns_cart_slot_device::write_h(offs_t offset, uint8_t data)
1130 {
1131 if (m_cart)
1132 m_cart->write_h(offset, data);
1133 }
1134
write_ram(offs_t offset,uint8_t data)1135 void base_sns_cart_slot_device::write_ram(offs_t offset, uint8_t data)
1136 {
1137 if (m_cart)
1138 m_cart->write_ram(offset, data);
1139 }
1140
chip_write(offs_t offset,uint8_t data)1141 void base_sns_cart_slot_device::chip_write(offs_t offset, uint8_t data)
1142 {
1143 if (m_cart)
1144 m_cart->chip_write(offset, data);
1145 }
1146
1147
1148 /*-------------------------------------------------
1149 Internal header logging
1150 -------------------------------------------------*/
1151
1152 /* We use this to convert the company_id in the header to int value to be passed in companies[] */
char_to_int_conv(char id)1153 static int char_to_int_conv( char id )
1154 {
1155 int value;
1156
1157 if (id == '1') value = 0x01;
1158 else if (id == '2') value = 0x02;
1159 else if (id == '3') value = 0x03;
1160 else if (id == '4') value = 0x04;
1161 else if (id == '5') value = 0x05;
1162 else if (id == '6') value = 0x06;
1163 else if (id == '7') value = 0x07;
1164 else if (id == '8') value = 0x08;
1165 else if (id == '9') value = 0x09;
1166 else if (id == 'A') value = 0x0a;
1167 else if (id == 'B') value = 0x0b;
1168 else if (id == 'C') value = 0x0c;
1169 else if (id == 'D') value = 0x0d;
1170 else if (id == 'E') value = 0x0e;
1171 else if (id == 'F') value = 0x0f;
1172 else value = 0x00;
1173
1174 return value;
1175 }
1176
1177 #define UNK "UNKNOWN"
1178
internal_header_logging(uint8_t * ROM,uint32_t len)1179 void base_sns_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len)
1180 {
1181 static const char *const cart_types[] =
1182 {
1183 "ROM (LoROM)",
1184 "ROM (HiROM)",
1185 "ROM (ExLoROM)",
1186 "ROM (ExHiROM)",
1187 "ROM, CX4",
1188 "ROM, DSP-1,2,3 (LoROM)",
1189 "ROM, DSP-1 (LoROM 2MB)",
1190 "ROM, DSP-1 (HiROM)",
1191 "ROM, DSP-4",
1192 "ROM, OBC-1",
1193 "ROM, SA-1",
1194 "ROM, S-DD1",
1195 "ROM, Super FX / FX2",
1196 "ROM, SPC7110",
1197 "ROM, SPC7110, RTC",
1198 "ROM, S-RTC",
1199 "ROM, Seta ST-010",
1200 "ROM, Seta ST-011",
1201 "ROM, Seta ST-018",
1202 "ROM, Z80GB (Super Game Boy)",
1203 "ROM, BS-X Base cart",
1204 "ROM, BS-X compatible (LoROM)",
1205 "ROM, BS-X compatible (HiROM)",
1206 "BS-X memory pack",
1207 "ROM, Sufami Turbo",
1208 "Sufami Turbo cart",
1209 // pirate cart types which are not recognized from fullpath
1210 UNK,
1211 UNK,
1212 UNK
1213 };
1214
1215 /* Some known countries */
1216 static const char *const countries[] =
1217 {
1218 /* 0*/ "Japan (NTSC)", "USA & Canada (NTSC)", "Europe, Oceania & Asia (PAL)", "Sweden (PAL)",
1219 /* 4*/ "Finland (PAL)", "Denmark (PAL)", "France (PAL)", "Holland (PAL)",
1220 /* 8*/ "Spain (PAL)", "Germany, Austria & Switzerland (PAL)", "Italy (PAL)", "Hong Kong & China (PAL)",
1221 /* c*/ "Indonesia (PAL)", "South Korea (NTSC)", UNK, UNK,
1222 };
1223
1224 /* Some known companies (integrations to the list from Snes9x) */
1225 static const char *const companies[] =
1226 {
1227 /* 0*/ "Invalid", "Nintendo", "Ajinomoto", "Imagineer-Zoom", "Chris Gray Enterprises Inc.", "Zamuse", "Falcom", UNK,
1228 /* 8*/ "Capcom", "HOT-B", "Jaleco", "Coconuts", "Rage Software", "Micronet", "Technos", "Mebio Software",
1229 /*10*/ "SHOUEi System", "Starfish", "Gremlin Graphics", "Electronic Arts", "NCS / Masaya", "COBRA Team", "Human/Field", "KOEI",
1230 /*18*/ "Hudson Soft", "Game Village", "Yanoman", UNK, "Tecmo", UNK, "Open System", "Virgin Games",
1231 /*20*/ "KSS", "Sunsoft", "POW", "Micro World", UNK, UNK, "Enix", "Loriciel/Electro Brain",
1232 /*28*/ "Kemco", "Seta Co.,Ltd.", "Culture Brain", "Irem Japan", "Pal Soft", "Visit Co.,Ltd.", "INTEC Inc.", "System Sacom Corp.",
1233 /*30*/ "Viacom New Media", "Carrozzeria", "Dynamic", "Nintendo", "Magifact", "Hect", UNK, UNK,
1234 /*38*/ "Capcom Europe", "Accolade Europe", UNK, "Arcade Zone", "Empire Software", "Loriciel", "Gremlin Graphics", UNK,
1235 /*40*/ "Seika Corp.", "UBI Soft", UNK, UNK, "LifeFitness Exertainment", UNK, "System 3", "Spectrum Holobyte",
1236 /*48*/ UNK, "Irem", UNK, "Raya Systems/Sculptured Software", "Renovation Products", "Malibu Games/Black Pearl", UNK, "U.S. Gold",
1237 /*50*/ "Absolute Entertainment", "Acclaim", "Activision", "American Sammy", "GameTek", "Hi Tech Expressions", "LJN Toys", UNK,
1238 /*58*/ UNK, UNK, "Mindscape", "Romstar, Inc.", UNK, "Tradewest", UNK, "American Softworks Corp.",
1239 /*60*/ "Titus", "Virgin Interactive Entertainment", "Maxis", "Origin/FCI/Pony Canyon", UNK, UNK, UNK, "Ocean",
1240 /*68*/ UNK, "Electronic Arts", UNK, "Laser Beam", UNK, UNK, "Elite", "Electro Brain",
1241 /*70*/ "Infogrames", "Interplay", "LucasArts", "Parker Brothers", "Konami", "STORM", UNK, UNK,
1242 /*78*/ "THQ Software", "Accolade Inc.", "Triffix Entertainment", UNK, "Microprose", UNK, UNK, "Kemco",
1243 /*80*/ "Misawa", "Teichio", "Namco Ltd.", "Lozc", "Koei", UNK, "Tokuma Shoten Intermedia", "Tsukuda Original",
1244 /*88*/ "DATAM-Polystar", UNK, UNK, "Bullet-Proof Software", "Vic Tokai", UNK, "Character Soft", "I\'\'Max",
1245 /*90*/ "Takara", "CHUN Soft", "Video System Co., Ltd.", "BEC", UNK, "Varie", "Yonezawa / S'Pal Corp.", "Kaneco",
1246 /*98*/ UNK, "Pack in Video", "Nichibutsu", "TECMO", "Imagineer Co.", UNK, UNK, UNK,
1247 /*a0*/ "Telenet", "Hori", UNK, UNK, "Konami", "K.Amusement Leasing Co.", UNK, "Takara",
1248 /*a8*/ UNK, "Technos Jap.", "JVC", UNK, "Toei Animation", "Toho", UNK, "Namco Ltd.",
1249 /*b0*/ "Media Rings Corp.", "ASCII Co. Activison", "Bandai", UNK, "Enix America", UNK, "Halken", UNK,
1250 /*b8*/ UNK, UNK, "Culture Brain", "Sunsoft", "Toshiba EMI", "Sony Imagesoft", UNK, "Sammy",
1251 /*c0*/ "Taito", UNK, "Kemco", "Square", "Tokuma Soft", "Data East", "Tonkin House", UNK,
1252 /*c8*/ "KOEI", UNK, "Konami USA", "NTVIC", UNK, "Meldac", "Pony Canyon", "Sotsu Agency/Sunrise",
1253 /*d0*/ "Disco/Taito", "Sofel", "Quest Corp.", "Sigma", "Ask Kodansha Co., Ltd.", UNK, "Naxat", UNK,
1254 /*d8*/ "Capcom Co., Ltd.", "Banpresto", "Tomy", "Acclaim", UNK, "NCS", "Human Entertainment", "Altron",
1255 /*e0*/ "Jaleco", UNK, "Yutaka", UNK, "T&ESoft", "EPOCH Co.,Ltd.", UNK, "Athena",
1256 /*e8*/ "Asmik", "Natsume", "King Records", "Atlus", "Sony Music Entertainment", UNK, "IGS", UNK,
1257 /*f0*/ UNK, "Motown Software", "Left Field Entertainment", "Beam Software", "Tec Magik", UNK, UNK, UNK,
1258 /*f8*/ UNK, "Cybersoft", UNK, "Psygnosis", UNK, UNK, "Davidson", UNK,
1259 };
1260
1261 int hilo_mode = snes_find_hilo_mode(this,ROM, len);
1262 char title[21], rom_id[4], company_id[2];
1263 int type = 0, company, addon, has_ram = 0, has_sram = 0;
1264 switch (hilo_mode)
1265 {
1266 case 0x007fc0:
1267 if ((ROM[0x007fd5] == 0x32) || (len > 0x401000))
1268 type = SNES_MODE22; // ExLoRom
1269 else
1270 type = SNES_MODE20; // LoRom
1271 type = SNES_MODE20; // LoRom & ExLoRom
1272 break;
1273 case 0x00ffc0:
1274 type = SNES_MODE21; // HiRom
1275 break;
1276 case 0x40ffc0:
1277 type = SNES_MODE25; // ExHiRom
1278 break;
1279 default:
1280 break;
1281 }
1282
1283 // detect Sufami Turbo...
1284 if (type == SNES_MODE20 && !memcmp(ROM, "BANDAI SFC-ADX", 14))
1285 {
1286 if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14))
1287 type = SNES_SUFAMITURBO;
1288 else
1289 type = SNES_STROM;
1290 }
1291
1292 // detect BS-X Base Cart
1293 if (!memcmp(ROM + hilo_mode, "Satellaview BS-X ", 21))
1294 type = SNES_BSX;
1295 // Detect BS-X Flash Cart
1296 if ((ROM[hilo_mode + 0x13] == 0x00 || ROM[hilo_mode + 0x13] == 0xff) && ROM[hilo_mode + 0x14] == 0x00)
1297 {
1298 uint8_t n15 = ROM[hilo_mode + 0x15];
1299 if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc)
1300 {
1301 if (ROM[hilo_mode + 0x1a] == 0x33 || ROM[hilo_mode + 0x1a] == 0xff)
1302 type = SNES_BSMEMPAK;
1303 }
1304 }
1305
1306 addon = snes_find_addon_chip(ROM, hilo_mode, len);
1307 if (addon != -1)
1308 {
1309 if (type == SNES_MODE20 && addon == SNES_DSP)
1310 {
1311 if (len > 0x100000)
1312 type = SNES_DSP_2MB;
1313 else
1314 type = SNES_DSP;
1315 }
1316 else if (type == SNES_MODE21 && addon == SNES_DSP)
1317 type = SNES_DSP_MODE21;
1318 else
1319 type = addon;
1320 }
1321
1322 /* Company */
1323 for (int i = 0; i < 2; i++)
1324 company_id[i] = ROM[hilo_mode - 0x10 + i];
1325 company = (char_to_int_conv(company_id[0]) << 4) + char_to_int_conv(company_id[1]);
1326 if (company == 0)
1327 company = ROM[hilo_mode + 0x1a];
1328
1329 /* ROM ID */
1330 for(int i = 0; i < 4; i++ )
1331 rom_id[i] = ROM[hilo_mode - 0x0e + i];
1332
1333 /* Title */
1334 for(int i = 0; i < 21; i++ )
1335 title[i] = ROM[hilo_mode + i];
1336
1337 /* RAM */
1338 if (((ROM[hilo_mode + 0x16] & 0xf) == 1) ||
1339 ((ROM[hilo_mode + 0x16] & 0xf) == 2) ||
1340 ((ROM[hilo_mode + 0x16] & 0xf) == 4) ||
1341 ((ROM[hilo_mode + 0x16] & 0xf) == 5))
1342 has_ram = 1;
1343
1344 /* SRAM */
1345 if (((ROM[hilo_mode + 0x16] & 0xf) == 2) ||
1346 ((ROM[hilo_mode + 0x16] & 0xf) == 5) ||
1347 ((ROM[hilo_mode + 0x16] & 0xf) == 6))
1348 has_sram = 1;
1349
1350 logerror( "ROM DETAILS\n" );
1351 logerror( "===========\n\n" );
1352 logerror( "\tTotal blocks: 0x%x\n", len);
1353 logerror( "\tROM bank size: %s \n",
1354 (type == SNES_MODE20) ? "LoROM" :
1355 (type == SNES_MODE21) ? "HiROM" :
1356 (type == SNES_MODE22) ? "ExLoROM" :
1357 (type == SNES_MODE25) ? "ExHiROM" : "Other (BSX or ST)" );
1358 logerror( "\tCompany: %s [%.2s]\n", companies[company], company_id );
1359 logerror( "\tROM ID: %.4s\n\n", rom_id );
1360
1361 logerror( "HEADER DETAILS\n" );
1362 logerror( "==============\n\n" );
1363 logerror( "\tName: %.21s\n", title );
1364 logerror( "\tSpeed: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf0) ? "FastROM" : "SlowROM", (ROM[hilo_mode + 0x15] & 0xf0) >> 4);
1365 logerror( "\tBank size: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf) ? "HiROM" : "LoROM", ROM[hilo_mode + 0x15] & 0xf);
1366
1367 logerror( "\tType: %s", cart_types[type]);
1368 if (has_ram)
1369 logerror( ", RAM");
1370 if (has_sram)
1371 logerror( ", SRAM");
1372 logerror( " [%d]\n", ROM[hilo_mode + 0x16]);
1373
1374 logerror( "\tSize: %d megabits [%d]\n", 1 << (ROM[hilo_mode + 0x17] - 7), ROM[hilo_mode + 0x17]);
1375 logerror( "\tSRAM: %d kilobits [%d]\n", ROM[hilo_mode + 0x18] * 8, ROM[hilo_mode + 0x18] );
1376 if (ROM[hilo_mode + 0x19] < ARRAY_LENGTH(countries))
1377 logerror( "\tCountry: %s [%d]\n", countries[ROM[hilo_mode + 0x19]], ROM[hilo_mode + 0x19]);
1378 else
1379 logerror( "\tCountry: Unknown [%d]\n", ROM[hilo_mode + 0x19]);
1380 logerror( "\tLicense: %s [%X]\n", companies[ROM[hilo_mode + 0x1a]], ROM[hilo_mode + 0x1a]);
1381 logerror( "\tVersion: 1.%d\n", ROM[hilo_mode + 0x1b]);
1382 logerror( "\tInv Checksum: %X %X\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c]);
1383 logerror( "\tChecksum: %X %X\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e]);
1384 logerror( "\tNMI Address: %2X%2Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a]);
1385 logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c]);
1386
1387 logerror( "\tMode: %d\n", type);
1388 }
1389