1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /*****************************************************************************************
4 
5     NES Cart PCBs Emulation
6 
7 ****************************************************************************************/
8 
9 struct nes_pcb
10 {
11 	const char              *slot_opt;
12 	int                     pcb_id;
13 };
14 
15 // Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
16 static const nes_pcb pcb_list[] =
17 {
18 	{ "nrom",             STD_NROM },
19 	{ "hvc_basic",        HVC_FAMBASIC },
20 	{ "nrom368",          STD_NROM368 },
21 	{ "nrom_gg",          GG_NROM },
22 	{ "uxrom",            STD_UXROM },
23 	{ "unrom_cc",         UXROM_CC },
24 	{ "cnrom",            STD_CNROM },
25 	{ "bandai_pt554",     BANDAI_PT554 },
26 	{ "cprom",            STD_CPROM },
27 	{ "axrom",            STD_AXROM },
28 	{ "pxrom",            STD_PXROM },
29 	{ "fxrom",            STD_FXROM },
30 	{ "bnrom",            STD_BXROM },
31 	{ "gxrom",            STD_GXROM },
32 	{ "un1rom",           STD_UN1ROM },
33 	{ "sxrom",            STD_SXROM },
34 	{ "sorom",            STD_SOROM },
35 	{ "sxrom_a",          STD_SXROM_A },
36 	{ "sorom_a",          STD_SOROM_A },
37 	{ "txrom",            STD_TXROM },
38 	{ "hkrom",            STD_HKROM },
39 	{ "tqrom",            STD_TQROM },
40 	{ "txsrom",           STD_TXSROM },
41 	{ "exrom",            STD_EXROM },
42 	{ "disksys",          STD_DISKSYS },
43 	{ "pal_zz",           PAL_ZZ },
44 	{ "nes_qj",           NES_QJ },
45 	{ "nes_event",        STD_EVENT },
46 	{ "discrete_74x139",  DIS_74X139X74 },
47 	{ "discrete_74x377",  DIS_74X377 },
48 	{ "discrete_74x161",  DIS_74X161X161X32 },
49 	{ "bitcorp_dis",      DIS_74X161X138 },
50 	{ "lz93d50",          BANDAI_LZ93 },
51 	{ "lz93d50_ep1",      BANDAI_LZ93EX1 },
52 	{ "lz93d50_ep2",      BANDAI_LZ93EX2 },
53 	{ "fcg",              BANDAI_FCG },
54 	{ "fjump2",           BANDAI_FJUMP2 },
55 	{ "datach",           BANDAI_DATACH },
56 	{ "karastudio",       BANDAI_KARAOKE },
57 	{ "oekakids",         BANDAI_OEKAKIDS },
58 	{ "g101",             IREM_G101 },
59 	{ "lrog017",          IREM_LROG017 },
60 	{ "h3001",            IREM_H3001 },
61 	{ "holydivr",         IREM_HOLYDIVR },
62 	{ "tam_s1",           IREM_TAM_S1 },
63 	{ "jf11",             JALECO_JF11 },
64 	{ "jf13",             JALECO_JF13 },
65 	{ "jf16",             JALECO_JF16 },
66 	{ "jf17",             JALECO_JF17 },
67 	{ "jf17pcm",          JALECO_JF17_ADPCM },
68 	{ "jf19",             JALECO_JF19 },
69 	{ "jf19pcm",          JALECO_JF19_ADPCM },
70 	{ "ss88006",          JALECO_SS88006 },
71 	{ "jf23",             JALECO_JF23 },
72 	{ "jf24",             JALECO_JF24 },
73 	{ "jf29",             JALECO_JF29 },
74 	{ "jf33",             JALECO_JF33 },
75 	{ "vrc1",             KONAMI_VRC1 },
76 	{ "vrc2",             KONAMI_VRC2 },
77 	{ "vrc3",             KONAMI_VRC3 },
78 	{ "vrc4",             KONAMI_VRC4 },
79 	{ "vrc6",             KONAMI_VRC6 },
80 	{ "vrc7",             KONAMI_VRC7 },
81 	{ "namcot_163",       NAMCOT_163 },
82 	{ "namcot_175",       NAMCOT_175 },
83 	{ "namcot_340",       NAMCOT_340 },
84 	{ "namcot_3433",      NAMCOT_34X3 },    // DxROM is a Nintendo board for US versions of the 3433/3443 games
85 	{ "namcot_3425",      NAMCOT_3425 },
86 	{ "namcot_3446",      NAMCOT_3446 },
87 	{ "sunsoft1",         SUNSOFT_1 },
88 	{ "sunsoft2",         SUNSOFT_2 },
89 	{ "sunsoft3",         SUNSOFT_3 },
90 	{ "sunsoft4",         SUNSOFT_4 },
91 	{ "sunsoft_dcs",      SUNSOFT_DCS },
92 	{ "sunsoft_fme7",     SUNSOFT_FME7 },  // JxROM is a Nintendo board for US versions of the Sunsoft FME7 games
93 	{ "sunsoft5a",        SUNSOFT_FME7 },
94 	{ "sunsoft5b",        SUNSOFT_5 },
95 	{ "tc0190fmc",        TAITO_TC0190FMC },
96 	{ "tc0190fmcp",       TAITO_TC0190FMCP },
97 	{ "tc0350fmr",        TAITO_TC0190FMC },
98 	{ "x1_005",           TAITO_X1_005 },    // two variants exist, depending on pin17 & pin31 connections
99 	{ "x1_017",           TAITO_X1_017 },
100 	{ "nina001",          AVE_NINA01 },
101 	{ "nina006",          AVE_NINA06 },
102 	{ "maxi15",           AVE_MAXI15 },
103 	{ "bf9093",           CAMERICA_BF9093 },
104 	{ "bf9096",           CAMERICA_BF9096 },
105 	{ "goldenfive",       CAMERICA_GOLDENFIVE },
106 	{ "ade"   ,           CAMERICA_ALADDIN },
107 	{ "cne_decathl",      CNE_DECATHLON },
108 	{ "cne_fsb",          CNE_FSB },
109 	{ "cne_shlz",         CNE_SHLZ },
110 	{ "nanjing",          NANJING_BOARD },  // mapper 163
111 	{ "ntdec_asder",      NTDEC_ASDER },    // mapper 112
112 	{ "ntdec_fh",         NTDEC_FIGHTINGHERO },     // mapper 193
113 	{ "sa009",            SACHEN_SA009 },
114 	{ "sa0036",           SACHEN_SA0036 },
115 	{ "sa0037",           SACHEN_SA0037 },
116 	{ "sa72007",          SACHEN_SA72007 },
117 	{ "sa72008",          SACHEN_SA72008 },
118 	{ "tca01",            SACHEN_TCA01 },
119 	{ "s8259a",           SACHEN_8259A },
120 	{ "s8259b",           SACHEN_8259B },
121 	{ "s8259c",           SACHEN_8259C },
122 	{ "s8259d",           SACHEN_8259D },
123 	{ "s74x374",          SACHEN_74LS374 },
124 	{ "s74x374a",         SACHEN_74LS374_ALT },   /* FIXME: Made up boards some different handling */
125 	{ "tcu01",            SACHEN_TCU01 },
126 	{ "tcu02",            SACHEN_TCU02 },
127 	{ "sa9602b",          SACHEN_SA9602B },
128 	{ "tengen_800008",    TENGEN_800008 },  /* FIXME: Is this the same as mapper 3? */
129 	{ "tengen_800032",    TENGEN_800032 },
130 	{ "tengen_800037",    TENGEN_800037 },
131 	{ "txc_22211",        TXC_22211 },
132 	{ "txc_dumarc",       TXC_DUMARACING },
133 	{ "txc_mjblock",      TXC_MJBLOCK },
134 	{ "txc_strikew",      TXC_STRIKEW },
135 	{ "txc_commandos",    TXC_COMMANDOS },
136 	{ "waixing_a",        WAIXING_TYPE_A },
137 	{ "waixing_a1",       WAIXING_TYPE_A1 },    /* FIXME: Made up boards the different CHRRAM banks (see Ji Jia Zhan Shi },  */
138 	{ "waixing_b",        WAIXING_TYPE_B },
139 	{ "waixing_c",        WAIXING_TYPE_C },
140 	{ "waixing_d",        WAIXING_TYPE_D },
141 	{ "waixing_e",        WAIXING_TYPE_E },
142 	{ "waixing_f",        WAIXING_TYPE_F },
143 	{ "waixing_g",        WAIXING_TYPE_G },
144 	{ "waixing_h",        WAIXING_TYPE_H },
145 	{ "waixing_h1",       WAIXING_TYPE_H1 },
146 	{ "waixing_i",        WAIXING_TYPE_I },
147 	{ "waixing_j",        WAIXING_TYPE_J },
148 	{ "waixing_sgz",      WAIXING_SGZ },
149 	{ "waixing_sgzlz",    WAIXING_SGZLZ },
150 	{ "waixing_sec",      WAIXING_SECURITY },
151 	{ "waixing_ffv",      WAIXING_FFV },
152 	{ "waixing_wxzs",     WAIXING_WXZS },
153 	{ "waixing_wxzs2",    WAIXING_WXZS2 },
154 	{ "waixing_dq8",      WAIXING_DQ8 },
155 	{ "waixing_sh2",      WAIXING_SH2 },
156 	{ "fs304",            WAIXING_FS304 },   // used in Zelda 3 by Waixing
157 	{ "cony",             CONY_BOARD },
158 	{ "yoko",             YOKO_BOARD },
159 	{ "hengg_srich",      HENGG_SRICH },
160 	{ "hengg_xhzs",       HENGG_XHZS },
161 	{ "hengg_shjy3",      HENGG_SHJY3 },    // mapper 253
162 	{ "hes",              HES_BOARD },
163 	{ "hosenkan",         HOSENKAN_BOARD },
164 	{ "ks7058",           KAISER_KS7058 },
165 	{ "ks202",            KAISER_KS202 },   // mapper 56
166 	{ "ks7022",           KAISER_KS7022 }, // mapper 175
167 	{ "ks7017",           KAISER_KS7017 },
168 	{ "ks7032",           KAISER_KS7032 },  //  mapper 142
169 	{ "ks7031",           KAISER_KS7031 },  //  used in Dracula II (FDS Conversion)
170 	{ "ks7012",           KAISER_KS7012 },     // used in Zanac (FDS Conversion)
171 	{ "ks7013b",          KAISER_KS7013B },    // used in Highway Star (FDS Conversion)
172 	{ "ks7016",           KAISER_KS7016 },  // used in Exciting Basketball (FDS Conversion)
173 	{ "ks7037",           KAISER_KS7037 },  // Metroid FDS Chinese
174 	{ "gs2015",           RCM_GS2015 },
175 	{ "gs2004",           RCM_GS2004 },
176 	{ "gs2013",           RCM_GS2013 },
177 	{ "tf9in1",           RCM_TF9IN1 },
178 	{ "3dblock",          RCM_3DBLOCK },    // NROM + IRQ?
179 	{ "racermate",        UNL_RACERMATE },  // mapper 168
180 	{ "agci_50282",       AGCI_50282 },
181 	{ "dreamtech01",      DREAMTECH_BOARD },
182 	{ "fukutake",         FUKUTAKE_BOARD },
183 	{ "futuremedia",      FUTUREMEDIA_BOARD },
184 	{ "magicseries",      MAGICSERIES_MD },
185 	{ "daou_306",         OPENCORP_DAOU306 },
186 	{ "subor0",           SUBOR_TYPE0 },
187 	{ "subor1",           SUBOR_TYPE1 },
188 	{ "subor2",           SUBOR_TYPE2 },
189 	{ "cc21",             UNL_CC21 },
190 	{ "xiaozy",           UNL_XIAOZY },
191 	{ "edu2k",            UNL_EDU2K },
192 	{ "t230",             UNL_T230 },
193 	{ "mk2",              UNL_MK2 },
194 	{ "zemina",           ZEMINA_BOARD },
195 	// misc bootleg boards
196 	{ "ax5705",           UNL_AX5705 },
197 	{ "sc127",            UNL_SC127 },
198 	{ "mariobaby",        BTL_MARIOBABY },
199 	{ "asnicol",          BTL_AISENSHINICOL },
200 	{ "smb3pirate",       BTL_SMB3 },
201 	{ "btl_dninja",       BTL_DRAGONNINJA },
202 	{ "whirl2706",        WHIRLWIND_2706 },
203 	{ "smb2j",            UNL_SMB2J },
204 	{ "smb2ja",           BTL_SMB2JA },
205 	{ "smb2jb",           BTL_SMB2JB },
206 	{ "09034a",           BTL_09034A },
207 	{ "tobidase",         BTL_TOBIDASE },  // mapper 120
208 	{ "dbz5",             REXSOFT_DBZ5 },
209 	{ "sl1632",           REXSOFT_SL1632 },
210 	{ "somari",           SOMARI_SL12 },  // mapper 116
211 	{ "nitra",            NITRA_TDA },
212 	{ "ks7057",           UNL_KS7057 },  // mapper 196 alt (for Street Fighter VI / Fight Street VI },
213 	{ "sbros11",          BTL_SBROS11 },
214 	{ "family4646",       BMC_FAMILY_4646 },
215 	{ "pikay2k",          BTL_PIKACHUY2K },  // mapper 254
216 	{ "8237",             UNL_8237 },
217 	{ "sg_lionk",         SUPERGAME_LIONKING },
218 	{ "sg_boog",          SUPERGAME_BOOGERMAN },
219 	{ "kasing",           KASING_BOARD },
220 	{ "kay",              KAY_BOARD },
221 	{ "h2288",            UNL_H2288 },
222 	{ "unl_6035052",      UNL_603_5052 },   // mapper 238?
223 	{ "txc_tw",           TXC_TW },
224 	{ "kof97",            UNL_KOF97 },
225 	{ "kof96",            UNL_KOF96 },
226 	{ "sfight3",          UNL_SF3 },
227 	{ "gouder",           GOUDER_37017 },
228 	{ "benshieng",        BMC_BENSHIENG },
229 	{ "action52",         ACTENT_ACT52 },
230 	{ "caltron6in1",      CALTRON_6IN1 },
231 	{ "rumblestation",    RUMBLESTATION_BOARD },     // mapper 46
232 	{ "svision16",        SVISION16_BOARD },
233 	{ "n625092",          UNL_N625092 },
234 	{ "a65as",            BMC_A65AS },
235 	{ "t262",             BMC_T262 },
236 	{ "novel1",           BMC_NOVEL1 },
237 	{ "novel2",           BMC_NOVEL2 },  // mapper 213... same as BMC-NOVELDIAMOND9999999IN1 board?
238 	{ "studyngame",       UNL_STUDYNGAME },  // mapper 39
239 	{ "sgun20in1",        BMC_SUPERGUN_20IN1 },
240 	{ "bmc_vt5201",       BMC_VT5201 },  // mapper 60 otherwise
241 	{ "bmc_d1038",        BMC_VT5201 },  // mapper 60?
242 	{ "810544c",          BMC_810544 },
243 	{ "ntd03",            BMC_NTD_03 },
244 	{ "bmc_gb63",         BMC_G63IN1 },
245 	{ "bmc_gka",          BMC_GKA },
246 	{ "bmc_gkb",          BMC_GKB },
247 	{ "bmc_ws",           BMC_WS },
248 	{ "bmc_hik300",       BMC_SUPERHIK_300IN1 },
249 	{ "bmc_s700",         BMC_SUPER_700IN1 },
250 	{ "bmc_ball11",       BMC_BALLGAMES_11IN1 },
251 	{ "bmc_22games",      BMC_22GAMES },
252 	{ "bmc_64y2k",        BMC_64IN1NR },
253 	{ "bmc_12in1",        BMC_12IN1 },
254 	{ "bmc_20in1",        BMC_20IN1 },
255 	{ "bmc_21in1",        BMC_21IN1 },
256 	{ "bmc_31in1",        BMC_31IN1 },
257 	{ "bmc_35in1",        BMC_35IN1 },
258 	{ "bmc_36in1",        BMC_36IN1 },
259 	{ "bmc_64in1",        BMC_64IN1 },
260 	{ "bmc_70in1",        BMC_70IN1 },
261 	{ "bmc_72in1",        BMC_72IN1 },
262 	{ "bmc_76in1",        BMC_76IN1 },
263 	{ "bmc_s42in1",       BMC_76IN1 },
264 	{ "bmc_110in1",       BMC_110IN1 },
265 	{ "bmc_150in1",       BMC_150IN1 },
266 	{ "bmc_190in1",       BMC_190IN1 },
267 	{ "bmc_800in1",       BMC_800IN1 },
268 	{ "bmc_1200in1",      BMC_1200IN1 },
269 	{ "bmc_8157",         BMC_8157 },
270 	{ "bmc_g146",         BMC_G146 },
271 	{ "bmc_11160",        BMC_11160 },
272 	{ "fk23c",            BMC_FK23C },
273 	{ "fk23ca",           BMC_FK23CA },
274 	{ "s24in1c03",        BMC_S24IN1SC03 },
275 	{ "bmc_15in1",        BMC_15IN1 },
276 	{ "bmc_sbig7in1",     BMC_SUPERBIG_7IN1 },
277 	{ "bmc_hik8in1",      BMC_HIK8IN1 },
278 	{ "bmc_hik4in1",      BMC_SUPERHIK_4IN1 },
279 	{ "bmc_mario7in1",    BMC_MARIOPARTY_7IN1 },
280 	{ "bmc_gold7in1",     BMC_GOLD_7IN1 },
281 	{ "bmc_gc6in1",       BMC_GOLDENCARD_6IN1 },
282 	{ "bmc_411120c",      BMC_411120C },
283 	{ "bmc_830118c",      BMC_830118C },
284 	{ "pjoy84",           BMC_PJOY84 },
285 	{ "bmc_gold150",      BMC_GOLD150 },
286 	{ "bmc_gold260",      BMC_GOLD260 },
287 	{ "bmc_power255",     BMC_CH001 },
288 	{ "bmc_s22games",     BMC_SUPER22 },
289 	{ "bmc_reset4",       BMC_4IN1RESET },
290 	{ "bmc_reset42",      BMC_42IN1RESET },
291 	{ "jyc_a",            JYCOMPANY_A },
292 	{ "jyc_b",            JYCOMPANY_B },
293 	{ "jyc_c",            JYCOMPANY_C },
294 	{ "tek90",            JYCOMPANY_A },
295 	{ "sa9602b",          SACHEN_SA9602B },
296 	{ "unl_shero",        SACHEN_SHERO },
297 	{ "mmalee2",          UNL_MMALEE },
298 	{ "unl_2708",         UNL_2708 },
299 	{ "unl_lh10",         UNL_LH10 },
300 	{ "unl_lh32",         UNL_LH32 },
301 	{ "unl_lh53",         UNL_LH53 },
302 	{ "unl_ac08",         UNL_AC08 },
303 	{ "unl_bb",           UNL_BB },
304 	{ "unl_malisb",       UNL_MALISB },
305 	{ "sgpipe",           BTL_SHUIGUAN },
306 	{ "rt01",             UNL_RT01 },   // Russian Test Cart
307 	{ "unl_whero",        UNL_WORLDHERO },
308 	{ "unl_43272",        UNL_43272 },
309 	{ "tf1201",           UNL_TF1201 },
310 	{ "unl_cfight",       UNL_CITYFIGHT },
311 	{ "nocash_nochr",     NOCASH_NOCHR },
312 	{ "nes_action53",     BTL_ACTION53 },
313 	{ "nes_2a03pur",      BTL_2A03_PURITANS },
314 	{ "ffe3",             FFE3_BOARD },
315 	{ "ffe4",             FFE4_BOARD },
316 	{ "ffe8",             FFE8_BOARD },
317 	{ "8237a",            UNSUPPORTED_BOARD },
318 	{ "ninjaryu",         UNSUPPORTED_BOARD },
319 	{ "unl_dance",        UNSUPPORTED_BOARD },
320 	{ "bmc_hik_kof",      UNSUPPORTED_BOARD },
321 	{ "onebus",           UNSUPPORTED_BOARD },
322 	{ "coolboy",          UNSUPPORTED_BOARD },
323 	{ "btl_900218",       UNSUPPORTED_BOARD },  // pirate The Lord of King, to be emulated soon
324 	{ "a9746",            UNSUPPORTED_BOARD },
325 	{ "pec586",           UNSUPPORTED_BOARD },
326 	{ "bmc_f15",          UNSUPPORTED_BOARD },  // 150-in-1 Unchained Melody
327 	{ "bmc_hp898f",       UNSUPPORTED_BOARD },  // Primasoft 9999999-in-1
328 	{ "bmc_8in1",         UNSUPPORTED_BOARD },  // Super 8-in-1 (Incl. Rockin' Kats)
329 	{ "unl_eh8813a",      UNSUPPORTED_BOARD },  // Dr. Mario II
330 	{ "unl_158b",         UNSUPPORTED_BOARD },  // Blood of Jurassic
331 	{ "unl_drgnfgt",      UNSUPPORTED_BOARD },  // Dragon Fighter by Flying Star
332 	{ "test",             TEST_BOARD },
333 	{ "unknown",          UNKNOWN_BOARD }  //  a few pirate dumps uses the wrong mapper...
334 };
335 
nes_pcb_lookup(const char * slot)336 static const nes_pcb *nes_pcb_lookup( const char *slot )
337 {
338 	for (auto & elem : pcb_list)
339 	{
340 		if (!core_stricmp(elem.slot_opt, slot))
341 			return &elem;
342 	}
343 	return nullptr;
344 }
345 
nes_id_lookup(int id)346 static const nes_pcb *nes_id_lookup( int id )
347 {
348 	for (auto & elem : pcb_list)
349 	{
350 		if (elem.pcb_id == id)
351 			return &elem;
352 	}
353 	return nullptr;
354 }
355 
nes_get_pcb_id(const char * slot)356 int nes_cart_slot_device::nes_get_pcb_id( const char *slot )
357 {
358 	const nes_pcb *pcb = nes_pcb_lookup(slot);
359 
360 	if (pcb == nullptr)
361 		fatalerror("Unimplemented PCB type %s\n", slot);
362 
363 	return pcb->pcb_id;
364 }
365 
366 
nes_get_slot(int pcb_id)367 const char * nes_cart_slot_device::nes_get_slot( int pcb_id )
368 {
369 	const nes_pcb *pcb = nes_id_lookup(pcb_id);
370 
371 	if (pcb == nullptr)
372 		fatalerror("Unimplemented PCB ID %d\n", pcb_id);
373 
374 	return pcb->slot_opt;
375 }
376 
377 
378 /*************************************************************
379 
380  nes_pcb_reset
381 
382  Resets the mmc bankswitch areas to their defaults.
383  It returns a value "err" that indicates if it was
384  successful. Possible values for err are:
385 
386  0 = success
387  1 = no pcb found
388  2 = pcb not supported
389 
390  *************************************************************/
391 
392 struct nes_cart_lines
393 {
394 	const char *tag;
395 	int line;
396 };
397 
398 static const struct nes_cart_lines nes_cart_lines_table[] =
399 {
400 	{ "PRG A0",    0 },
401 	{ "PRG A1",    1 },
402 	{ "PRG A2",    2 },
403 	{ "PRG A3",    3 },
404 	{ "PRG A4",    4 },
405 	{ "PRG A5",    5 },
406 	{ "PRG A6",    6 },
407 	{ "PRG A7",    7 },
408 	{ "CHR A10",  10 },
409 	{ "CHR A11",  11 },
410 	{ "CHR A12",  12 },
411 	{ "CHR A13",  13 },
412 	{ "CHR A14",  14 },
413 	{ "CHR A15",  15 },
414 	{ "CHR A16",  16 },
415 	{ "CHR A17",  17 },
416 	{ "NC",      127 },
417 	{ nullptr }
418 };
419 
nes_cart_get_line(const char * feature)420 static int nes_cart_get_line( const char *feature )
421 {
422 	const struct nes_cart_lines *nes_line = &nes_cart_lines_table[0];
423 
424 	if (feature == nullptr)
425 		return 128;
426 
427 	while (nes_line->tag)
428 	{
429 		if (strcmp(nes_line->tag, feature) == 0)
430 			break;
431 
432 		nes_line++;
433 	}
434 
435 	return nes_line->line;
436 }
437 
438 struct n163_vol_lines
439 {
440 	const char *tag;
441 	int line;
442 };
443 
444 static const struct n163_vol_lines n163_vol_table[] =
445 {
446 	{ "SUBMAPPER 0",    0 },
447 	{ "SUBMAPPER 1",    1 },
448 	{ "SUBMAPPER 2",    2 },
449 	{ "SUBMAPPER 3",    3 },
450 	{ "SUBMAPPER 4",    4 },
451 	{ "SUBMAPPER 5",    5 },
452 	{ nullptr }
453 };
454 
n163_get_submapper_num(const char * feature)455 static int n163_get_submapper_num( const char *feature )
456 {
457 	const struct n163_vol_lines *n163_line = &n163_vol_table[0];
458 
459 	if (feature == nullptr)
460 		return 128;
461 
462 	while (n163_line->tag)
463 	{
464 		if (strcmp(n163_line->tag, feature) == 0)
465 			break;
466 
467 		n163_line++;
468 	}
469 
470 	return n163_line->line;
471 }
472 
call_load_pcb()473 void nes_cart_slot_device::call_load_pcb()
474 {
475 	uint32_t vram_size = 0, prgram_size = 0, battery_size = 0, mapper_sram_size = 0;
476 	// SETUP step 1: getting PRG, VROM, VRAM sizes
477 	uint32_t prg_size = get_software_region_length("prg");
478 	uint32_t vrom_size = get_software_region_length("chr");
479 	vram_size = get_software_region_length("vram");
480 	vram_size += get_software_region_length("vram2");
481 
482 	// validate the xml fields
483 	if (!prg_size)
484 		fatalerror("No PRG entry for this software! Please check if the xml list got corrupted\n");
485 	if (prg_size < 0x8000)
486 		fatalerror("PRG entry is too small! Please check if the xml list got corrupted\n");
487 
488 	// SETUP step 2: getting PCB and other settings
489 	if (get_feature("slot"))
490 		m_pcb_id = nes_get_pcb_id(get_feature("slot"));
491 	else
492 		m_pcb_id = NO_BOARD;
493 
494 	// SETUP step 3: storing the info needed for emulation
495 	if (get_software_region("bwram") != nullptr)
496 		battery_size = get_software_region_length("bwram");
497 
498 	if (get_software_region("wram") != nullptr)
499 		prgram_size = get_software_region_length("wram");
500 
501 	if (get_feature("mirroring"))
502 	{
503 		const char *mirroring = get_feature("mirroring");
504 		if (!strcmp(mirroring, "horizontal"))
505 			m_cart->set_mirroring(PPU_MIRROR_HORZ);
506 		if (!strcmp(mirroring, "vertical"))
507 			m_cart->set_mirroring(PPU_MIRROR_VERT);
508 		if (!strcmp(mirroring, "high"))
509 			m_cart->set_mirroring(PPU_MIRROR_HIGH);
510 		if (!strcmp(mirroring, "low"))
511 			m_cart->set_mirroring(PPU_MIRROR_LOW);
512 		if (!strcmp(mirroring, "4screen"))
513 		{
514 			// A few boards uses 4-screen mirroring: Gauntlet (DDROM or TRR1ROM or Tengen 800004),
515 			// Rad Racer II (TVROM), and Napoleon Senki (IREM LROG017 with 74*161/161/21/138)
516 			m_cart->set_four_screen_vram(true);
517 			m_cart->set_mirroring(PPU_MIRROR_4SCREEN);
518 		}
519 		if (!strcmp(mirroring, "pcb_controlled"))
520 		{
521 			// A few boards have variants with hardcoded mirroring and variants with mapper
522 			// controlled mirroring. We use a variable to avoid the need of dupe devices.
523 			// See e.g. HES 6-in-1 vs other HES games, Irem Major League vs other G-101 games,
524 			// Sunsoft-2 Shanghai vs Mito Koumon, Camerica BF9093 games vs BF9097 games, etc.
525 			// Boards where all games control mirroring do not make real use of this.
526 			m_cart->set_pcb_ctrl_mirror(true);
527 		}
528 	}
529 
530 	/* Check for pins in specific boards which require them */
531 	if (m_pcb_id == STD_CNROM)
532 	{
533 		int mask = 0, state = 0;
534 
535 		if (get_feature("chr-pin26") != nullptr)
536 		{
537 			mask |= 0x01;
538 			state |= !strcmp(get_feature("chr-pin26"), "CE") ? 0x01 : 0;
539 		}
540 		if (get_feature("chr-pin27") != nullptr)
541 		{
542 			mask |= 0x02;
543 			state |= !strcmp(get_feature("chr-pin27"), "CE") ? 0x02 : 0;
544 		}
545 
546 		m_cart->set_ce(mask, state);
547 	}
548 
549 	if (m_pcb_id == TAITO_X1_005 && get_feature("x1-pin17") != nullptr && get_feature("x1-pin31") != nullptr)
550 	{
551 		if (!strcmp(get_feature("x1-pin17"), "CIRAM A10") && !strcmp(get_feature("x1-pin31"), "NC"))
552 			m_cart->set_x1_005_alt(true);
553 	}
554 
555 	if (m_pcb_id == KONAMI_VRC2)
556 	{
557 		m_cart->set_vrc_lines(nes_cart_get_line(get_feature("vrc2-pin3")),
558 						nes_cart_get_line(get_feature("vrc2-pin4")),
559 						(nes_cart_get_line(get_feature("vrc2-pin21")) != 10) ? 1 : 0);
560 //      osd_printf_error("VRC-2, pin3: A%d, pin4: A%d, pin21: %d\n", nes_cart_get_line(get_feature("vrc2-pin3")), nes_cart_get_line(get_feature("vrc2-pin4")),
561 //                              nes_cart_get_line(get_feature("vrc2-pin21")));
562 	}
563 
564 	if (m_pcb_id == KONAMI_VRC4)
565 	{
566 		m_cart->set_vrc_lines(nes_cart_get_line(get_feature("vrc4-pin3")),
567 						nes_cart_get_line(get_feature("vrc4-pin4")),
568 						0);
569 //      osd_printf_error("VRC-4, pin3: A%d, pin4: A%d\n", nes_cart_get_line(get_feature("vrc4-pin3"), nes_cart_get_line(get_feature("vrc4-pin4"));
570 	}
571 
572 	if (m_pcb_id == KONAMI_VRC6)
573 	{
574 		m_cart->set_vrc_lines(nes_cart_get_line(get_feature("vrc6-pin9")),
575 						nes_cart_get_line(get_feature("vrc6-pin10")),
576 						0);
577 //      osd_printf_error("VRC-6, pin9: A%d, pin10: A%d\n", nes_cart_get_line(get_feature("vrc6-pin9"), nes_cart_get_line(get_feature("vrc6-pin10"));
578 	}
579 
580 	if (m_pcb_id == STD_HKROM || m_pcb_id == TAITO_X1_017)
581 		mapper_sram_size = m_cart->get_mapper_sram_size();
582 
583 	if (m_pcb_id == TAITO_X1_005 || m_pcb_id == NAMCOT_163)
584 	{
585 		if (get_feature("batt"))
586 			mapper_sram_size = m_cart->get_mapper_sram_size();
587 	}
588 
589 	if (m_pcb_id == NAMCOT_163)
590 	{
591 		if (get_feature("n163-vol"))
592 			m_cart->set_n163_vol(n163_get_submapper_num(get_feature("n163-vol")));
593 	}
594 
595 
596 	// pirate variants of boards with bus conflict are often not suffering from it
597 	// and actually games glitch if bus conflict is emulated...
598 	if (get_feature("bus_conflict") && !strcmp(get_feature("bus_conflict"), "no"))
599 		m_cart->set_bus_conflict(false);
600 
601 
602 	// SETUP step 4: logging what we have found
603 	logerror("Loaded game from softlist:\n");
604 	if (get_feature("pcb"))
605 	{
606 		logerror("-- PCB: %s", get_feature("pcb"));
607 		if (m_pcb_id == UNSUPPORTED_BOARD)
608 			logerror(" (currently not supported by MESS)");
609 		logerror("\n");
610 	}
611 	logerror("-- PRG 0x%x (%d x 16k chunks)\n", prg_size, prg_size / 0x4000);
612 	logerror("-- VROM 0x%x (%d x 8k chunks)\n", vrom_size, vrom_size / 0x2000);
613 	logerror("-- VRAM 0x%x (%d x 8k chunks)\n", vram_size, vram_size / 0x2000);
614 	logerror("-- PRG NVWRAM: %d\n", battery_size + mapper_sram_size);
615 	logerror("-- PRG WRAM: %d\n",  prgram_size);
616 
617 	// SETUP steps 5/6: allocate pointers for PRG/VROM and load the data!
618 	m_cart->prg_alloc(prg_size, tag());
619 	memcpy(m_cart->get_prg_base(), get_software_region("prg"), prg_size);
620 	if (vrom_size)
621 	{
622 		m_cart->vrom_alloc(vrom_size, tag());
623 		memcpy(m_cart->get_vrom_base(), get_software_region("chr"), vrom_size);
624 	}
625 
626 	// SETUP steps 7: allocate the remaining pointer, when needed
627 	if (vram_size)
628 		m_cart->vram_alloc(vram_size);
629 	if (prgram_size)
630 		m_cart->prgram_alloc(prgram_size);
631 
632 	// also nes_smb2j_device needs WRAM initialized to 0xff? check!
633 	if (m_pcb_id == UNL_SMB2J)
634 		memset(m_cart->get_prgram_base(), 0xff, prgram_size);
635 
636 	// Attempt to load a battery file for this ROM
637 	// A few boards have internal RAM with a battery (MMC6, Taito X1-005 & X1-017, etc.)
638 	if (battery_size || mapper_sram_size)
639 	{
640 		uint32_t tot_size = battery_size + mapper_sram_size;
641 		std::vector<uint8_t> temp_nvram(tot_size);
642 
643 		// some games relies on specific battery patterns to work
644 		// (e.g. Silva Saga does not work with SRAM fully initialized to 0x00)
645 		// and we use the info from xml here to prepare a default NVRAM
646 		std::vector<uint8_t> default_nvram(tot_size);
647 		if (battery_size)
648 			memcpy(&default_nvram[0], get_software_region("bwram"), battery_size);
649 		if (mapper_sram_size)
650 			memset(&default_nvram[battery_size], 0, mapper_sram_size);
651 
652 		// load battery (using default if no battery exists)
653 		battery_load(&temp_nvram[0], tot_size, &default_nvram[0]);
654 
655 		// copy battery into PCB arrays
656 		if (battery_size)
657 		{
658 			m_cart->battery_alloc(battery_size);
659 			memcpy(m_cart->get_battery_base(), &temp_nvram[0], battery_size);
660 		}
661 		if (mapper_sram_size)
662 			memcpy(m_cart->get_mapper_sram_base(), &temp_nvram[battery_size], mapper_sram_size);
663 	}
664 }
665