1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4 
5 
6  NES/Famicom cartridge emulation for Nanjing PCBs
7 
8  TODO:
9  - Emulate the variants often assigned to mapper 162/164 (and investigate connection with Waixing FS-304)!
10 
11  ***********************************************************************************************************/
12 
13 
14 #include "emu.h"
15 #include "nanjing.h"
16 
17 #include "video/ppu2c0x.h"
18 
19 
20 #ifdef NES_PCB_DEBUG
21 #define VERBOSE 1
22 #else
23 #define VERBOSE 0
24 #endif
25 
26 #define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
27 
28 
29 //-------------------------------------------------
30 //  constructor
31 //-------------------------------------------------
32 
33 DEFINE_DEVICE_TYPE(NES_NANJING, nes_nanjing_device, "nes_nanjing", "NES Cart Nanjing PCB")
34 
35 
nes_nanjing_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)36 nes_nanjing_device::nes_nanjing_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
37 	: nes_nrom_device(mconfig, NES_NANJING, tag, owner, clock)
38 	, m_count(0)
39 	, m_latch1(0)
40 	, m_latch2(0)
41 	, m_ppu(*this, ":ppu") // FIXME: this dependency should not exist
42 {
43 }
44 
~nes_nanjing_device()45 nes_nanjing_device::~nes_nanjing_device()
46 {
47 }
48 
49 
50 
51 
device_start()52 void nes_nanjing_device::device_start()
53 {
54 	common_start();
55 	save_item(NAME(m_count));
56 	save_item(NAME(m_latch1));
57 	save_item(NAME(m_latch2));
58 	save_item(NAME(m_reg));
59 }
60 
pcb_reset()61 void nes_nanjing_device::pcb_reset()
62 {
63 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
64 	prg16_89ab(m_prg_chunks - 2);
65 	prg16_cdef(m_prg_chunks - 1);
66 	chr8(0, m_chr_source);
67 
68 	m_count = 0xff;
69 	m_latch1 = 0;
70 	m_latch2 = 0;
71 	m_reg[0] = 0xff;
72 	m_reg[1] = 0;
73 }
74 
75 
76 
77 
78 
79 /*-------------------------------------------------
80  mapper specific handlers
81  -------------------------------------------------*/
82 
83 /*-------------------------------------------------
84 
85  Bootleg Board by Nanjing
86 
87  Games: A lot of pirate originals
88 
89  iNES: mapper 163
90 
91  In MESS: Unsupported.
92 
93  -------------------------------------------------*/
94 
hblank_irq(int scanline,int vblank,int blanked)95 void nes_nanjing_device::hblank_irq(int scanline, int vblank, int blanked)
96 {
97 	if (BIT(m_reg[0], 7))
98 	{
99 		if (scanline == 127)
100 		{
101 			chr4_0(1, CHRRAM);
102 			chr4_4(1, CHRRAM);
103 		}
104 
105 		if (scanline == 239)
106 		{
107 			chr4_0(0, CHRRAM);
108 			chr4_4(0, CHRRAM);
109 		}
110 	}
111 
112 }
113 
write_l(offs_t offset,uint8_t data)114 void nes_nanjing_device::write_l(offs_t offset, uint8_t data)
115 {
116 	LOG_MMC(("nanjing write_l, offset: %04x, data: %02x\n", offset, data));
117 
118 	offset += 0x100;
119 
120 	if (offset < 0x1000)
121 		return;
122 
123 	if (offset == 0x1100)   // 0x5100
124 	{
125 		if (data == 6)
126 			prg32(3);
127 		return;
128 	}
129 
130 	if (offset == 0x1101)   // 0x5101
131 	{
132 		uint8_t temp = m_count;
133 		m_count = data;
134 
135 		if ((temp & ~data) & 1)
136 		{
137 			m_latch2 ^= 0xff;
138 		}
139 	}
140 
141 	switch (offset & 0x300)
142 	{
143 		case 0x000:
144 		case 0x200:
145 			m_reg[BIT(offset, 9)] = data;
146 			if (!BIT(m_reg[0], 7) && m_ppu->get_current_scanline() <= 127)
147 				chr8(0, CHRRAM);
148 			break;
149 		case 0x300:
150 			m_latch1 = data;
151 			break;
152 	}
153 
154 	prg32((m_reg[0] & 0x0f) | ((m_reg[1] & 0x0f) << 4));
155 }
156 
read_l(offs_t offset)157 uint8_t nes_nanjing_device::read_l(offs_t offset)
158 {
159 	uint8_t value = 0;
160 	LOG_MMC(("nanjing read_l, offset: %04x\n", offset));
161 
162 	offset += 0x100;
163 
164 	if (offset < 0x1000)
165 		return 0;
166 
167 	switch (offset & 0x700)
168 	{
169 		case 0x100:
170 			value = m_latch1;
171 			break;
172 		case 0x500:
173 			value = m_latch2 & m_latch1;
174 			break;
175 		case 0x000:
176 		case 0x200:
177 		case 0x300:
178 		case 0x400:
179 		case 0x600:
180 		case 0x700:
181 			value = 4;
182 			break;
183 	}
184 	return value;
185 }
186