1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4 
5 
6  NES/Famicom cartridge emulation for pirate cart PCBs
7 
8 
9  Here we emulate the various PCBs used by Asian & Korean pirate games
10 
11  TODO:
12  - Are the scrolling glitches (check status bar) in Magic Dragon correct? FWIW, NEStopia behaves similarly
13 
14  ***********************************************************************************************************/
15 
16 
17 #include "emu.h"
18 #include "pirate.h"
19 
20 #include "video/ppu2c0x.h"      // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
21 #include "screen.h"
22 
23 
24 #ifdef NES_PCB_DEBUG
25 #define VERBOSE 1
26 #else
27 #define VERBOSE 0
28 #endif
29 
30 #define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
31 
32 
33 //-------------------------------------------------
34 //  constructor
35 //-------------------------------------------------
36 
37 DEFINE_DEVICE_TYPE(NES_AGCI_50282,  nes_agci_device,        "nes_agci50282",   "NES Cart AGCI 50282 PCB")
38 DEFINE_DEVICE_TYPE(NES_DREAMTECH01, nes_dreamtech_device,   "nes_dreamtech",   "NES Cart Dreamtech01 PCB")
39 DEFINE_DEVICE_TYPE(NES_FUKUTAKE,    nes_fukutake_device,    "nes_futuremedia", "NES Cart Fukutake Study Box PCB")
40 DEFINE_DEVICE_TYPE(NES_FUTUREMEDIA, nes_futuremedia_device, "nes_fukutake",    "NES Cart FutureMedia PCB")
41 DEFINE_DEVICE_TYPE(NES_MAGSERIES,   nes_magseries_device,   "nes_magseries",   "NES Cart Magical Series PCB")
42 DEFINE_DEVICE_TYPE(NES_DAOU306,     nes_daou306_device,     "nes_daou306",     "NES Cart Daou 306 PCB")
43 DEFINE_DEVICE_TYPE(NES_CC21,        nes_cc21_device,        "nes_cc21",        "NES Cart CC-21 PCB")
44 DEFINE_DEVICE_TYPE(NES_XIAOZY,      nes_xiaozy_device,      "nes_xiaozy",      "NES Cart Xiao Zhuan Yuan PCB")
45 DEFINE_DEVICE_TYPE(NES_EDU2K,       nes_edu2k_device,       "nes_edu2k",       "NES Cart Educational Computer 2000 PCB")
46 DEFINE_DEVICE_TYPE(NES_T230,        nes_t230_device,        "nes_t230",        "NES Cart T-230 PCB")
47 DEFINE_DEVICE_TYPE(NES_MK2,         nes_mk2_device,         "nes_mk2",         "NES Cart Mortal Kombat 2 PCB")
48 DEFINE_DEVICE_TYPE(NES_WHERO,       nes_whero_device,       "nes_whero",       "NES Cart World Heroes PCB")
49 DEFINE_DEVICE_TYPE(NES_43272,       nes_43272_device,       "nes_43272",       "NES Cart UNL-43272 PCB")
50 DEFINE_DEVICE_TYPE(NES_TF1201,      nes_tf1201_device,      "nes_tf1201",      "NES Cart UNL-TF1201 PCB")
51 DEFINE_DEVICE_TYPE(NES_CITYFIGHT,   nes_cityfight_device,   "nes_cityfight",   "NES Cart City Fighter PCB")
52 
53 
nes_agci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)54 nes_agci_device::nes_agci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
55 	: nes_nrom_device(mconfig, NES_AGCI_50282, tag, owner, clock)
56 {
57 }
58 
nes_dreamtech_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)59 nes_dreamtech_device::nes_dreamtech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
60 	: nes_nrom_device(mconfig, NES_DREAMTECH01, tag, owner, clock)
61 {
62 }
63 
nes_fukutake_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)64 nes_fukutake_device::nes_fukutake_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
65 	: nes_nrom_device(mconfig, NES_FUKUTAKE, tag, owner, clock), m_latch(0)
66 {
67 }
68 
nes_futuremedia_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)69 nes_futuremedia_device::nes_futuremedia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
70 	: nes_nrom_device(mconfig, NES_FUTUREMEDIA, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_clear(0), m_irq_enable(0)
71 {
72 }
73 
nes_magseries_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)74 nes_magseries_device::nes_magseries_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
75 	: nes_nrom_device(mconfig, NES_MAGSERIES, tag, owner, clock)
76 {
77 }
78 
nes_daou306_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)79 nes_daou306_device::nes_daou306_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
80 	: nes_nrom_device(mconfig, NES_DAOU306, tag, owner, clock)
81 {
82 }
83 
nes_cc21_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)84 nes_cc21_device::nes_cc21_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
85 	: nes_nrom_device(mconfig, NES_CC21, tag, owner, clock)
86 {
87 }
88 
nes_xiaozy_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)89 nes_xiaozy_device::nes_xiaozy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
90 	: nes_nrom_device(mconfig, NES_XIAOZY, tag, owner, clock)
91 {
92 }
93 
nes_edu2k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)94 nes_edu2k_device::nes_edu2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
95 	: nes_nrom_device(mconfig, NES_EDU2K, tag, owner, clock)
96 {
97 }
98 
nes_t230_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)99 nes_t230_device::nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
100 	: nes_nrom_device(mconfig, NES_T230, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_mode(0), m_irq_enable(0), m_irq_enable_latch(0)
101 {
102 }
103 
nes_mk2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)104 nes_mk2_device::nes_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
105 	: nes_nrom_device(mconfig, NES_MK2, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_clear(0), m_irq_enable(0)
106 {
107 }
108 
nes_whero_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)109 nes_whero_device::nes_whero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
110 	: nes_nrom_device(mconfig, NES_WHERO, tag, owner, clock), m_reg(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0)
111 {
112 }
113 
nes_43272_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)114 nes_43272_device::nes_43272_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
115 	: nes_nrom_device(mconfig, NES_43272, tag, owner, clock), m_latch(0)
116 {
117 }
118 
nes_tf1201_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)119 nes_tf1201_device::nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
120 	: nes_nrom_device(mconfig, NES_TF1201, tag, owner, clock), m_prg(0), m_swap(0), m_irq_count(0), m_irq_enable(0), m_irq_enable_latch(0)
121 {
122 }
123 
nes_cityfight_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)124 nes_cityfight_device::nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
125 	: nes_nrom_device(mconfig, NES_CITYFIGHT, tag, owner, clock), m_prg_reg(0), m_prg_mode(0), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
126 {
127 }
128 
129 
130 
131 
device_start()132 void nes_agci_device::device_start()
133 {
134 	common_start();
135 }
136 
pcb_reset()137 void nes_agci_device::pcb_reset()
138 {
139 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
140 	prg32(0);
141 	chr8(0, m_chr_source);
142 }
143 
device_start()144 void nes_dreamtech_device::device_start()
145 {
146 	common_start();
147 }
148 
pcb_reset()149 void nes_dreamtech_device::pcb_reset()
150 {
151 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
152 	prg16_89ab(0);
153 	prg16_cdef(8);
154 	chr8(0, m_chr_source);
155 }
156 
device_start()157 void nes_fukutake_device::device_start()
158 {
159 	common_start();
160 	save_item(NAME(m_latch));
161 
162 	// 2816 (?) bytes of RAM
163 	save_item(NAME(m_ram));
164 }
165 
pcb_reset()166 void nes_fukutake_device::pcb_reset()
167 {
168 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
169 	prg16_89ab(0);
170 	prg16_cdef(0);
171 	chr8(0, m_chr_source);
172 
173 	m_latch = 0;
174 }
175 
device_start()176 void nes_futuremedia_device::device_start()
177 {
178 	common_start();
179 	save_item(NAME(m_irq_clear));
180 	save_item(NAME(m_irq_enable));
181 	save_item(NAME(m_irq_count));
182 	save_item(NAME(m_irq_count_latch));
183 }
184 
pcb_reset()185 void nes_futuremedia_device::pcb_reset()
186 {
187 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
188 	prg16_89ab(0);
189 	prg16_cdef(m_prg_chunks - 1);
190 	chr8(0, m_chr_source);
191 
192 	m_irq_clear = 0;
193 	m_irq_enable = 0;
194 	m_irq_count = m_irq_count_latch = 0;
195 }
196 
device_start()197 void nes_magseries_device::device_start()
198 {
199 	common_start();
200 }
201 
pcb_reset()202 void nes_magseries_device::pcb_reset()
203 {
204 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
205 	prg32(0);
206 	chr8(0, m_chr_source);
207 }
208 
device_start()209 void nes_daou306_device::device_start()
210 {
211 	common_start();
212 	save_item(NAME(m_reg));
213 }
214 
pcb_reset()215 void nes_daou306_device::pcb_reset()
216 {
217 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
218 	prg16_89ab(m_prg_chunks - 2);
219 	prg16_cdef(m_prg_chunks - 1);
220 	chr8(0, m_chr_source);
221 	set_nt_mirroring(PPU_MIRROR_LOW);
222 
223 	memset(m_reg, 0, sizeof(m_reg));
224 }
225 
device_start()226 void nes_cc21_device::device_start()
227 {
228 	common_start();
229 }
230 
pcb_reset()231 void nes_cc21_device::pcb_reset()
232 {
233 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
234 	prg32(0);
235 	chr8(0, m_chr_source);
236 }
237 
device_start()238 void nes_xiaozy_device::device_start()
239 {
240 	common_start();
241 }
242 
pcb_reset()243 void nes_xiaozy_device::pcb_reset()
244 {
245 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
246 	prg32((m_prg_chunks - 1) >> 1);
247 	chr8(0, m_chr_source);
248 }
249 
device_start()250 void nes_edu2k_device::device_start()
251 {
252 	common_start();
253 	save_item(NAME(m_latch));
254 }
255 
pcb_reset()256 void nes_edu2k_device::pcb_reset()
257 {
258 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
259 	prg32(0);
260 	chr8(0, m_chr_source);
261 
262 	m_latch = 0;
263 }
264 
device_start()265 void nes_t230_device::device_start()
266 {
267 	common_start();
268 	save_item(NAME(m_irq_mode));
269 	save_item(NAME(m_irq_enable));
270 	save_item(NAME(m_irq_enable_latch));
271 	save_item(NAME(m_irq_count));
272 	save_item(NAME(m_irq_count_latch));
273 	save_item(NAME(m_mmc_vrom_bank));
274 }
275 
pcb_reset()276 void nes_t230_device::pcb_reset()
277 {
278 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
279 	prg16_89ab(0);
280 	prg16_cdef(m_prg_chunks - 1);
281 	chr8(0, m_chr_source);
282 
283 	m_irq_mode = 0;
284 	m_irq_enable = m_irq_enable_latch = 0;
285 	m_irq_count = m_irq_count_latch = 0;
286 
287 	memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
288 }
289 
device_start()290 void nes_mk2_device::device_start()
291 {
292 	common_start();
293 	save_item(NAME(m_irq_clear));
294 	save_item(NAME(m_irq_enable));
295 	save_item(NAME(m_irq_count));
296 	save_item(NAME(m_irq_count_latch));
297 }
298 
pcb_reset()299 void nes_mk2_device::pcb_reset()
300 {
301 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
302 	prg16_89ab(m_prg_chunks - 1);
303 	prg16_cdef(m_prg_chunks - 1);
304 	chr8(0, m_chr_source);
305 	set_nt_mirroring(PPU_MIRROR_VERT);
306 
307 	m_irq_clear = 0;
308 	m_irq_enable = 0;
309 	m_irq_count = m_irq_count_latch = 0;
310 }
311 
312 
device_start()313 void nes_whero_device::device_start()
314 {
315 	common_start();
316 	save_item(NAME(m_irq_enable));
317 	save_item(NAME(m_irq_enable_latch));
318 	save_item(NAME(m_irq_count));
319 	save_item(NAME(m_irq_count_latch));
320 	save_item(NAME(m_reg));
321 	save_item(NAME(m_mmc_vrom_bank));
322 }
323 
pcb_reset()324 void nes_whero_device::pcb_reset()
325 {
326 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
327 	prg16_89ab(0);
328 	prg16_cdef(m_prg_chunks - 1);
329 	chr8(0x100, m_chr_source);
330 
331 	m_irq_enable = 0;
332 	m_irq_enable_latch = 0;
333 	m_irq_count = 0;
334 	m_irq_count_latch = 0;
335 
336 	m_reg = 0;
337 	memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
338 }
339 
device_start()340 void nes_43272_device::device_start()
341 {
342 	common_start();
343 	save_item(NAME(m_latch));
344 }
345 
pcb_reset()346 void nes_43272_device::pcb_reset()
347 {
348 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
349 	prg32((m_prg_chunks - 1) >> 1);
350 	chr8(0, m_chr_source);
351 
352 	m_latch = 0x81;
353 }
354 
device_start()355 void nes_tf1201_device::device_start()
356 {
357 	common_start();
358 	save_item(NAME(m_prg));
359 	save_item(NAME(m_swap));
360 	save_item(NAME(m_irq_enable));
361 	save_item(NAME(m_irq_enable_latch));
362 	save_item(NAME(m_irq_count));
363 	save_item(NAME(m_mmc_vrom_bank));
364 }
365 
pcb_reset()366 void nes_tf1201_device::pcb_reset()
367 {
368 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
369 	prg16_89ab(0);
370 	prg16_cdef(m_prg_chunks - 1);
371 	chr8(0, m_chr_source);
372 
373 	memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
374 	m_prg = 0;
375 	m_swap = 0;
376 	m_irq_enable = 0;
377 	m_irq_enable_latch = 0;
378 	m_irq_count = 0;
379 }
380 
device_start()381 void nes_cityfight_device::device_start()
382 {
383 	common_start();
384 	irq_timer = timer_alloc(TIMER_IRQ);
385 	irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
386 
387 	save_item(NAME(m_prg_reg));
388 	save_item(NAME(m_prg_mode));
389 	save_item(NAME(m_irq_enable));
390 	save_item(NAME(m_irq_count));
391 	save_item(NAME(m_mmc_vrom_bank));
392 }
393 
pcb_reset()394 void nes_cityfight_device::pcb_reset()
395 {
396 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
397 	prg16_89ab(0);
398 	prg16_cdef(m_prg_chunks - 1);
399 	chr8(0, m_chr_source);
400 
401 	memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
402 	m_prg_reg = 0;
403 	m_prg_mode = 0;
404 	m_irq_enable = 0;
405 	m_irq_count = 0;
406 }
407 
408 
409 
410 /*-------------------------------------------------
411  mapper specific handlers
412  -------------------------------------------------*/
413 
414 /*-------------------------------------------------
415 
416  AGCI 50282 bootleg board emulation
417 
418  Games: Death Race
419 
420  iNES: mapper 144
421 
422  In MESS: Supported.
423 
424  -------------------------------------------------*/
425 
write_h(offs_t offset,uint8_t data)426 void nes_agci_device::write_h(offs_t offset, uint8_t data)
427 {
428 	LOG_MMC(("agci write_h, offset: %04x, data: %02x\n", offset, data));
429 
430 	// this pcb is subject to bus conflict
431 	uint8_t temp = account_bus_conflict(offset, 0xff);
432 	data = (data & temp) | (temp & 1);
433 
434 	chr8(data >> 4, CHRROM);
435 	prg32(data);
436 }
437 
438 /*-------------------------------------------------
439 
440  Board DREAMTECH01
441 
442  Games: Korean Igo
443 
444  In MESS: Supported
445 
446  -------------------------------------------------*/
447 
write_l(offs_t offset,uint8_t data)448 void nes_dreamtech_device::write_l(offs_t offset, uint8_t data)
449 {
450 	LOG_MMC(("dreamtech write_l, offset: %04x, data: %02x\n", offset, data));
451 	offset += 0x100;
452 
453 	if (offset == 0x1020)   /* 0x5020 */
454 		prg16_89ab(data);
455 }
456 
457 /*-------------------------------------------------
458 
459  Bootleg Board by Fukutake
460 
461  Games: Study Box
462 
463  iNES: mapper 186
464 
465  In MESS: Unsupported.
466 
467 
468  -------------------------------------------------*/
469 
write_l(offs_t offset,uint8_t data)470 void nes_fukutake_device::write_l(offs_t offset, uint8_t data)
471 {
472 	LOG_MMC(("fukutake write_l, offset: %04x, data: %02x\n", offset, data));
473 	offset += 0x100;
474 
475 	if (offset >= 0x200 && offset < 0x400)
476 	{
477 		if (offset & 1)
478 			prg16_89ab(data);
479 		else
480 			m_latch = data >> 6;
481 	}
482 	else if (offset >= 0x400 && offset < 0xf00)
483 		m_ram[offset - 0x400] = data;
484 }
485 
read_l(offs_t offset)486 uint8_t nes_fukutake_device::read_l(offs_t offset)
487 {
488 	LOG_MMC(("fukutake read_l, offset: %04x\n", offset));
489 	offset += 0x100;
490 
491 	if (offset >= 0x200 && offset < 0x400)
492 	{
493 		if (offset == 0x200 || offset == 0x201 || offset == 0x203)
494 			return 0x00;
495 		else if (offset == 0x202)
496 			return 0x40;
497 		else
498 			return 0xff;
499 	}
500 	else if (offset >= 0x400 && offset < 0xf00)
501 		return m_ram[offset - 0x400];
502 
503 	return 0;
504 }
505 
write_m(offs_t offset,uint8_t data)506 void nes_fukutake_device::write_m(offs_t offset, uint8_t data)
507 {
508 	LOG_MMC(("fukutake write_m, offset: %04x, data: %02x\n", offset, data));
509 	m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
510 }
511 
read_m(offs_t offset)512 uint8_t nes_fukutake_device::read_m(offs_t offset)
513 {
514 	LOG_MMC(("fukutake read_m, offset: %04x\n", offset));
515 	return m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)];
516 }
517 
518 /*-------------------------------------------------
519 
520  Bootleg Board by Future Media
521 
522  Games: Crayon Shin-chan (C), San Guo Zhi 4 - Chi Bi Feng Yun
523 
524  iNES: mapper 117
525 
526  In MESS: Unsupported.
527 
528  -------------------------------------------------*/
529 
hblank_irq(int scanline,int vblank,int blanked)530 void nes_futuremedia_device::hblank_irq(int scanline, int vblank, int blanked)
531 {
532 	//  if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
533 	{
534 		if (m_irq_enable && m_irq_count)
535 		{
536 			m_irq_count--;
537 			if (!m_irq_count)
538 				hold_irq_line();
539 		}
540 	}
541 }
542 
write_h(offs_t offset,uint8_t data)543 void nes_futuremedia_device::write_h(offs_t offset, uint8_t data)
544 {
545 	LOG_MMC(("futuremedia write_h, offset: %04x, data: %02x\n", offset, data));
546 
547 	switch (offset)
548 	{
549 		case 0x0000:
550 			prg8_89(data);
551 			break;
552 		case 0x0001:
553 			prg8_ab(data);
554 			break;
555 		case 0x0002:
556 			prg8_cd(data);
557 			break;
558 		case 0x0003:
559 			prg8_ef(data);
560 			break;
561 		case 0x2000:
562 		case 0x2001:
563 		case 0x2002:
564 		case 0x2003:
565 		case 0x2004:
566 		case 0x2005:
567 		case 0x2006:
568 		case 0x2007:
569 			chr1_x(offset & 0x07, data, CHRROM);
570 			break;
571 
572 		case 0x5000:
573 			set_nt_mirroring(BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
574 			break;
575 
576 		case 0x4001:
577 			m_irq_count_latch = data;
578 			break;
579 		case 0x4002:
580 			// IRQ cleared
581 			break;
582 		case 0x4003:
583 			m_irq_count = m_irq_count_latch;
584 			break;
585 		case 0x6000:
586 			m_irq_enable = data & 0x01;
587 			break;
588 	}
589 }
590 
591 /*-------------------------------------------------
592 
593  Bootleg Board by Magic Series
594 
595  Games: Magic Dragon
596 
597  Very simple mapper: writes to 0x8000-0xffff set prg32 and chr8
598  banks
599 
600  iNES: mapper 107
601 
602  In MESS: Supported.
603 
604  -------------------------------------------------*/
605 
write_h(offs_t offset,uint8_t data)606 void nes_magseries_device::write_h(offs_t offset, uint8_t data)
607 {
608 	LOG_MMC(("magseries write_h, offset: %04x, data: %02x\n", offset, data));
609 
610 	prg32(data >> 1);
611 	chr8(data, CHRROM);
612 }
613 
614 /*-------------------------------------------------
615 
616  Open Corp DAOU306 board
617 
618  Games: Metal Force (K)
619 
620  iNES: mapper 156
621 
622  In MESS: Supported.
623 
624  Notes: Metal Force and Buzz & Waldog only use the first 4
625  regs and no mirroring. Janggun ui Adeul uses all features
626 
627  -------------------------------------------------*/
628 
write_h(offs_t offset,uint8_t data)629 void nes_daou306_device::write_h(offs_t offset, uint8_t data)
630 {
631 	LOG_MMC(("daou306 write_h, offset: %04x, data: %02x\n", offset, data));
632 	int reg = BIT(offset, 2) ? 8 : 0;
633 
634 	switch (offset)
635 	{
636 		case 0x4000:
637 		case 0x4004:
638 			m_reg[reg + 0] = data;
639 			chr1_0(m_reg[0] | (m_reg[8] << 8), CHRROM);
640 			break;
641 		case 0x4001:
642 		case 0x4005:
643 			m_reg[reg + 1] = data;
644 			chr1_1(m_reg[1] | (m_reg[9] << 8), CHRROM);
645 			break;
646 		case 0x4002:
647 		case 0x4006:
648 			m_reg[reg + 2] = data;
649 			chr1_2(m_reg[2] | (m_reg[10] << 8), CHRROM);
650 			break;
651 		case 0x4003:
652 		case 0x4007:
653 			m_reg[reg + 3] = data;
654 			chr1_3(m_reg[3] | (m_reg[11] << 8), CHRROM);
655 			break;
656 		case 0x4008:
657 		case 0x400c:
658 			m_reg[reg + 4] = data;
659 			chr1_4(m_reg[4] | (m_reg[12] << 8), CHRROM);
660 			break;
661 		case 0x4009:
662 		case 0x400d:
663 			m_reg[reg + 5] = data;
664 			chr1_5(m_reg[5] | (m_reg[13] << 8), CHRROM);
665 			break;
666 		case 0x400a:
667 		case 0x400e:
668 			m_reg[reg + 6] = data;
669 			chr1_6(m_reg[6] | (m_reg[14] << 8), CHRROM);
670 			break;
671 		case 0x400b:
672 		case 0x400f:
673 			m_reg[reg + 7] = data;
674 			chr1_7(m_reg[7] | (m_reg[15] << 8), CHRROM);
675 			break;
676 		case 0x4010:
677 			prg16_89ab(data);
678 			break;
679 		case 0x4014:
680 			if (data & 1)
681 				set_nt_mirroring(PPU_MIRROR_HORZ);
682 			else
683 				set_nt_mirroring(PPU_MIRROR_VERT);
684 			break;
685 	}
686 }
687 
688 /*-------------------------------------------------
689 
690  Board UNL-CC-21
691 
692  Games: Mi Hun Che
693 
694  In MESS: Supported
695 
696  -------------------------------------------------*/
697 
write_h(offs_t offset,uint8_t data)698 void nes_cc21_device::write_h(offs_t offset, uint8_t data)
699 {
700 	LOG_MMC(("cc21 write_h, offset: %04x, data: %02x\n", offset, data));
701 
702 	set_nt_mirroring(BIT(offset, 1) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
703 	chr8((offset & 0x01), CHRROM);
704 }
705 
706 /*-------------------------------------------------
707 
708  Bootleg Board for Xiao Zhuan Yuan
709 
710  Games: Shu Qi Yu - Zhi Li Xiao Zhuan Yuan
711 
712  Very simple mapper: writes to 0x5ff1 set prg32 (to data>>1),
713  while writes to 0x5ff2 set chr8
714 
715  iNES: mapper 176
716 
717  In MESS: Supported.
718 
719  -------------------------------------------------*/
720 
write_l(offs_t offset,uint8_t data)721 void nes_xiaozy_device::write_l(offs_t offset, uint8_t data)
722 {
723 	LOG_MMC(("xiaozy write_l, offset: %04x, data: %02x\n", offset, data));
724 
725 	switch (offset)
726 	{
727 		case 0x1ef1:    /* 0x5ff1 */
728 			prg32(data >> 1);
729 			break;
730 		case 0x1ef2:    /* 0x5ff2 */
731 			chr8(data, CHRROM);
732 			break;
733 	}
734 }
735 
736 /*-------------------------------------------------
737 
738  UNL-EDU2000
739 
740  -------------------------------------------------*/
741 
write_h(offs_t offset,uint8_t data)742 void nes_edu2k_device::write_h(offs_t offset, uint8_t data)
743 {
744 	LOG_MMC(("edu2k write_h, offset: %04x, data: %02x\n", offset, data));
745 
746 	prg32(data & 0x1f);
747 	m_latch = (data & 0xc0) >> 6;
748 }
749 
write_m(offs_t offset,uint8_t data)750 void nes_edu2k_device::write_m(offs_t offset, uint8_t data)
751 {
752 	LOG_MMC(("edu2k write_m, offset: %04x, data: %02x\n", offset, data));
753 	m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
754 }
755 
read_m(offs_t offset)756 uint8_t nes_edu2k_device::read_m(offs_t offset)
757 {
758 	LOG_MMC(("edu2k read_m, offset: %04x\n", offset));
759 	return m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)];
760 }
761 
762 /*-------------------------------------------------
763 
764  Board UNL-T-230
765 
766  Games: Dragon Ball Z IV (Unl)
767 
768  This mapper appears to be similar to Konami VRC-2
769  but the game has no VROM and only 1 VRAM bank, so we
770  completely skip the chr bankswitch. If other games
771  using the same board and using CHR should surface,
772  we need to investigate this...
773 
774  In MESS: Supported
775 
776  -------------------------------------------------*/
777 
778 // Identical to Konami IRQ
hblank_irq(int scanline,int vblank,int blanked)779 void nes_t230_device::hblank_irq(int scanline, int vblank, int blanked)
780 {
781 	/* Increment & check the IRQ scanline counter */
782 	if (m_irq_enable && (++m_irq_count == 0x100))
783 	{
784 		m_irq_count = m_irq_count_latch;
785 		m_irq_enable = m_irq_enable_latch;
786 		hold_irq_line();
787 	}
788 }
789 
write_h(offs_t offset,uint8_t data)790 void nes_t230_device::write_h(offs_t offset, uint8_t data)
791 {
792 	LOG_MMC(("t230 write_h, offset: %04x, data: %02x\n", offset, data));
793 
794 	switch (offset & 0x700c)
795 	{
796 		case 0x0000:
797 			break;
798 		case 0x2000:
799 			prg16_89ab(data);
800 			break;
801 		case 0x1000:
802 		case 0x1004:
803 		case 0x1008:
804 		case 0x100c:
805 			switch (data & 0x03)
806 			{
807 				case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
808 				case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
809 				case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
810 				case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
811 			}
812 			break;
813 
814 		case 0x7000:
815 			m_irq_count_latch &= ~0x0f;
816 			m_irq_count_latch |= data & 0x0f;
817 			break;
818 		case 0x7004:
819 			m_irq_count_latch &= ~0xf0;
820 			m_irq_count_latch |= (data << 4) & 0xf0;
821 			break;
822 		case 0x7008:
823 			m_irq_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
824 			m_irq_enable = data & 0x02;
825 			m_irq_enable_latch = data & 0x01;
826 			if (data & 0x02)
827 				m_irq_count = m_irq_count_latch;
828 			break;
829 
830 		default:
831 			logerror("unl_t230_w uncaught offset: %04x value: %02x\n", offset, data);
832 			break;
833 	}
834 }
835 
836 /*-------------------------------------------------
837 
838  Bootleg Board for MK2
839 
840  Games: Mortal Kombat II, Street Fighter III, Super Mario
841  Kart Rider
842 
843  This board uses an IRQ system very similar to MMC3. We indeed
844  use mapper4_irq, but there is some small glitch!
845 
846  iNES: mapper 91
847 
848  In MESS: Supported.
849 
850  -------------------------------------------------*/
851 
852 // Same IRQ as MMC3
hblank_irq(int scanline,int vblank,int blanked)853 void nes_mk2_device::hblank_irq( int scanline, int vblank, int blanked )
854 {
855 	if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
856 	{
857 		int prior_count = m_irq_count;
858 		if ((m_irq_count == 0) || m_irq_clear)
859 			m_irq_count = m_irq_count_latch;
860 		else
861 			m_irq_count--;
862 
863 		if (m_irq_enable && !blanked && (m_irq_count == 0) && (prior_count || m_irq_clear))
864 		{
865 			LOG_MMC(("irq fired, scanline: %d\n", scanline));
866 			hold_irq_line();
867 		}
868 	}
869 	m_irq_clear = 0;
870 }
871 
write_m(offs_t offset,uint8_t data)872 void nes_mk2_device::write_m(offs_t offset, uint8_t data)
873 {
874 	LOG_MMC(("mk2 write_m, offset: %04x, data: %02x\n", offset, data));
875 
876 	switch (offset & 0x1000)
877 	{
878 		case 0x0000:
879 			switch (offset & 0x03)
880 			{
881 				case 0x00: chr2_0(data, CHRROM); break;
882 				case 0x01: chr2_2(data, CHRROM); break;
883 				case 0x02: chr2_4(data, CHRROM); break;
884 				case 0x03: chr2_6(data, CHRROM); break;
885 			}
886 			break;
887 		case 0x1000:
888 			switch (offset & 0x03)
889 			{
890 				case 0x00: prg8_89(data); break;
891 				case 0x01: prg8_ab(data); break;
892 				case 0x02: m_irq_enable = 0; m_irq_count = 0; break;
893 				case 0x03: m_irq_enable = 1; m_irq_count = 7; break;
894 			}
895 			break;
896 		default:
897 			logerror("mk2 write_m, uncaught addr: %04x value: %02x\n", offset + 0x6000, data);
898 			break;
899 	}
900 }
901 
902 
903 /*-------------------------------------------------
904 
905  UNL-WOLRDHERO board emulation
906 
907 
908  iNES:
909 
910  -------------------------------------------------*/
911 
912 // Same as Konami VRC IRQ...
hblank_irq(int scanline,int vblank,int blanked)913 void nes_whero_device::hblank_irq(int scanline, int vblank, int blanked)
914 {
915 	/* Increment & check the IRQ scanline counter */
916 	if (m_irq_enable && (++m_irq_count == 0x100))
917 	{
918 		m_irq_count = m_irq_count_latch;
919 		m_irq_enable = m_irq_enable_latch;
920 		hold_irq_line();
921 	}
922 }
923 
write_h(offs_t offset,uint8_t data)924 void nes_whero_device::write_h(offs_t offset, uint8_t data)
925 {
926 	int bank, shift, mask1, mask2;
927 	LOG_MMC(("World Hero write_h, offset: %04x, data: %02x\n", offset, data));
928 
929 	switch (offset & 0x70c3)
930 	{
931 		case 0x0000:
932 			if (!m_reg)
933 				prg8_89(data);
934 			else
935 				prg8_cd(data);
936 			break;
937 
938 		case 0x1000:
939 			switch (data & 0x03)
940 			{
941 				case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
942 				case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
943 				case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
944 				case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
945 			}
946 			break;
947 
948 		case 0x1002:
949 		case 0x1080:
950 			if (m_reg != (data & 2))
951 			{
952 				m_reg = data & 2;
953 				// swap banks!
954 				prg8_89(m_prg_bank[2]);
955 				prg8_cd(m_prg_bank[0]);
956 			}
957 			break;
958 
959 		case 0x2000:
960 			prg8_ab(data);
961 			break;
962 
963 		case 0x3000: case 0x3001: case 0x3002: case 0x3003:
964 		case 0x4000: case 0x4001: case 0x4002: case 0x4003:
965 		case 0x5000: case 0x5001: case 0x5002: case 0x5003:
966 		case 0x6000: case 0x6001: case 0x6002: case 0x6003:
967 			bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(offset, 1);
968 			shift = (offset & 1) << 2;
969 			mask1 = shift ? 0x00f : 0xff0;
970 			mask2 = shift ? 0xff0 : 0x00f;
971 			m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & mask1) | ((data << shift) & mask2);
972 			chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
973 			break;
974 
975 		case 0x7000:
976 			m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
977 			break;
978 
979 		case 0x7001:
980 			m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
981 			break;
982 
983 		case 0x7002:
984 			//          m_irq_mode = data & 0x04;   // currently not implemented: 0 = prescaler mode / 1 = CPU mode
985 			m_irq_enable = data & 0x02;
986 			m_irq_enable_latch = data & 0x01;
987 			if (data & 0x02)
988 				m_irq_count = m_irq_count_latch;
989 			break;
990 
991 		case 0x7003:
992 			m_irq_enable = m_irq_enable_latch;
993 			break;
994 	}
995 }
996 
997 
998 /*-------------------------------------------------
999 
1000  UNL-43272
1001 
1002  Games: Gaau Hok Gwong Cheung
1003 
1004  In MESS: Preliminary Supported
1005 
1006  -------------------------------------------------*/
1007 
write_h(offs_t offset,uint8_t data)1008 void nes_43272_device::write_h(offs_t offset, uint8_t data)
1009 {
1010 	LOG_MMC(("unl_43272 write_h, offset: %04x, data: %02x\n", offset, data));
1011 
1012 	if ((m_latch & 0x81) == 0x81)
1013 		prg32((m_latch & 0x38) >> 3);
1014 
1015 	m_latch = offset & 0xffff;
1016 }
1017 
1018 
read_h(offs_t offset)1019 uint8_t nes_43272_device::read_h(offs_t offset)
1020 {
1021 	uint8_t mask = (m_latch & 0x400) ? 0xfe : 0xff;
1022 	LOG_MMC(("unl_43272 read_h, offset: %04x\n", offset));
1023 
1024 	return hi_access_rom(offset & mask);
1025 }
1026 
1027 
1028 /*-------------------------------------------------
1029 
1030  UNL-TF1201
1031 
1032  Games:
1033 
1034  In MESS: Preliminary Supported
1035 
1036  -------------------------------------------------*/
1037 
hblank_irq(int scanline,int vblank,int blanked)1038 void nes_tf1201_device::hblank_irq(int scanline, int vblank, int blanked)
1039 {
1040 	if (m_irq_enable_latch != m_irq_enable && scanline < 240)
1041 		m_irq_count -= 8;
1042 
1043 	if (m_irq_enable)
1044 	{
1045 		m_irq_count++;
1046 		if ((m_irq_count & 0xff) == 238)
1047 			hold_irq_line();
1048 	}
1049 }
1050 
update_prg()1051 void nes_tf1201_device::update_prg()
1052 {
1053 	prg8_89(m_swap ? 0xff : m_prg);
1054 	prg8_cd(m_swap ? m_prg : 0xff );
1055 }
1056 
write_h(offs_t offset,uint8_t data)1057 void nes_tf1201_device::write_h(offs_t offset, uint8_t data)
1058 {
1059 	int bank;
1060 	LOG_MMC(("unl_tf1201 write_h, offset: %04x, data: %02x\n", offset, data));
1061 
1062 	offset = (offset & 0x7003) | ((offset & 0x0c) >> 2);    // nestopia does not OR here...
1063 
1064 	switch (offset & 0x7003)
1065 	{
1066 		case 0x0000:
1067 			m_prg = data;
1068 			update_prg();
1069 			break;
1070 		case 0x1000:
1071 			set_nt_mirroring(BIT(data, 0) ?  PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
1072 			break;
1073 		case 0x1001:
1074 			m_swap = data & 0x03;
1075 			update_prg();
1076 			break;
1077 		case 0x2000:
1078 			prg8_ab(data);
1079 			break;
1080 		case 0x3000: case 0x3001: case 0x3002: case 0x3003:
1081 		case 0x4000: case 0x4001: case 0x4002: case 0x4003:
1082 		case 0x5000: case 0x5001: case 0x5002: case 0x5003:
1083 		case 0x6000: case 0x6001: case 0x6002: case 0x6003:
1084 			bank = (((offset - 0x3000) >> 11) | (offset & 0x1)) & 0x7;
1085 			if (offset & 2)
1086 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
1087 			else
1088 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
1089 			chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
1090 			break;
1091 		case 0x7000:
1092 			m_irq_count = (m_irq_count & 0xf0) | (data & 0x0f);
1093 			break;
1094 		case 0x7001:
1095 		case 0x7003:
1096 			m_irq_enable_latch = m_irq_enable;
1097 			m_irq_enable = BIT(data, 1);
1098 			break;
1099 		case 0x7002:
1100 			m_irq_count = (m_irq_count & 0x0f) | ((data & 0x0f) << 4);
1101 			break;
1102 	}
1103 }
1104 
1105 
1106 /*-------------------------------------------------
1107 
1108  UNL-CITYFIGHT
1109 
1110  Games:
1111 
1112  Additional audio register not emulated yet!
1113 
1114  In MESS: Preliminary Supported
1115 
1116  -------------------------------------------------*/
1117 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1118 void nes_cityfight_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
1119 {
1120 	if (id == TIMER_IRQ)
1121 	{
1122 		if (m_irq_enable)
1123 		{
1124 			if (!m_irq_count)
1125 			{
1126 				hold_irq_line();
1127 				m_irq_count = 0xffff;
1128 			}
1129 			else
1130 				m_irq_count--;
1131 		}
1132 	}
1133 }
1134 
update_prg()1135 void nes_cityfight_device::update_prg()
1136 {
1137 	prg32(m_prg_reg >> 2);
1138 	if (!m_prg_mode)
1139 		prg8_cd(m_prg_reg);
1140 }
1141 
write_h(offs_t offset,uint8_t data)1142 void nes_cityfight_device::write_h(offs_t offset, uint8_t data)
1143 {
1144 	int bank;
1145 	LOG_MMC(("unl_cityfight write_h, offset: %04x, data: %02x\n", offset, data));
1146 
1147 	switch (offset & 0x700c)
1148 	{
1149 		case 0x1000:
1150 			switch (data & 0x03)
1151 			{
1152 				case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
1153 				case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
1154 				case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
1155 				case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
1156 			}
1157 			m_prg_reg = data & 0xc;
1158 			break;
1159 		case 0x1004:
1160 		case 0x1008:
1161 		case 0x100c:
1162 			if (offset & 0x800)
1163 				LOG_MMC(("Extended Audio write, data %x!", data & 0x0f));//pcmwrite(0x4011, (V & 0xf) << 3);
1164 			else
1165 				m_prg_reg = data & 0xc;
1166 			break;
1167 
1168 
1169 		case 0x2000: case 0x2004: case 0x2008: case 0x200c:
1170 			bank = 2 + BIT(offset, 3);
1171 			if (offset & 4)
1172 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
1173 			else
1174 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
1175 			chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
1176 			break;
1177 		case 0x3000: case 0x3004: case 0x3008: case 0x300c:
1178 			bank = 4 + BIT(offset, 3);
1179 			if (offset & 4)
1180 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
1181 			else
1182 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
1183 			chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
1184 			break;
1185 		case 0x5000: case 0x5004: case 0x5008: case 0x500c:
1186 			bank = 0 + BIT(offset, 3);
1187 			if (offset & 4)
1188 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
1189 			else
1190 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
1191 			chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
1192 			break;
1193 		case 0x6000: case 0x6004: case 0x6008: case 0x600c:
1194 			bank = 6 + BIT(offset, 3);
1195 			if (offset & 4)
1196 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
1197 			else
1198 				m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
1199 			chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
1200 			break;
1201 
1202 		case 0x4000:
1203 		case 0x4004:
1204 		case 0x4008:
1205 		case 0x400c:
1206 			m_prg_mode = data & 1;
1207 
1208 		case 0x7000:
1209 			m_irq_count = (m_irq_count & 0x1e0) | ((data & 0x0f) << 1);
1210 			break;
1211 		case 0x7004:
1212 			m_irq_count = (m_irq_count & 0x1e) | ((data & 0x0f) << 5);
1213 			break;
1214 		case 0x7008:
1215 			m_irq_enable = BIT(data, 1);
1216 			break;
1217 	}
1218 }
1219 
1220 
1221 #ifdef UNUSED_FUNCTION
1222 /*-------------------------------------------------
1223 
1224  FUJIYA Board - mapper 170 according to NEStopia
1225 
1226  Is this possibly for the Fujiya Famikase series
1227  of educational titles? Is there any dump around?
1228 
1229  -------------------------------------------------*/
1230 
device_start()1231 void nes_fujiya_device::device_start()
1232 {
1233 	common_start();
1234 	save_item(NAME(m_latch));
1235 }
1236 
pcb_reset()1237 void nes_fujiya_device::pcb_reset()
1238 {
1239 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
1240 	prg16_89ab(0);
1241 	prg16_cdef(0);
1242 	chr8(0, m_chr_source);
1243 
1244 	m_latch = 0;
1245 }
1246 
write_m(offs_t offset,uint8_t data)1247 void nes_fujiya_device::write_m(offs_t offset, uint8_t data)
1248 {
1249 	LOG_MMC(("fujiya write_m, offset: %04x, data: %02x\n", offset, data));
1250 	offset += 0x6000;
1251 
1252 	if (offset == 0x6502 || offset == 0x7000)
1253 		m_latch = (data & 0x40) << 1;
1254 }
1255 
read_m(offs_t offset)1256 uint8_t nes_fujiya_device::read_m(offs_t offset)
1257 {
1258 	LOG_MMC(("fujiya read_m, offset: %04x\n", offset));
1259 	offset += 0x6000;
1260 
1261 	if (offset == 0x7001 || offset == 0x7777)
1262 		return m_latch | ((offset >> 8) & 0x7f);
1263 
1264 	return get_open_bus();  // open bus
1265 }
1266 #endif
1267