1 // NMK004 device
2 // Based on MAME device by David Haywood and trap15
3 
4 #include "burnint.h"
5 #include "m68000_intf.h"
6 #include "tlcs90_intf.h"
7 #include "nmk004.h"
8 #include "burn_ym2203.h"
9 #include "msm6295.h"
10 
11 UINT8 *NMK004OKIROM0;
12 UINT8 *NMK004OKIROM1;
13 UINT8 *NMK004PROGROM;
14 
15 static UINT8 *ram;
16 
17 static UINT8 to_nmk004 = 0;
18 static UINT8 to_main = 0;
19 static INT32 bankdata[2] = { 0, 0 };
20 
21 static INT32 nmk004_initted = 0;
22 
nmk004_tlcs90_read(UINT32 address)23 static UINT8 nmk004_tlcs90_read(UINT32 address)
24 {
25 	if (address >= 0xfec0 && address < 0xffc0) {	// internal ram
26 		return ram[0x800 + (address - 0xfec0)];
27 	}
28 
29 	switch (address)
30 	{
31 		case 0xf800:
32 		case 0xf801:
33 			return BurnYM2203Read(0, address & 1);
34 
35 		case 0xf900:
36 			return MSM6295Read(0);
37 
38 		case 0xfa00:
39 			return MSM6295Read(1);
40 
41 		case 0xfb00:
42 			return to_nmk004;
43 	}
44 
45 	return 0;
46 }
47 
oki_bankswitch(INT32 chip,INT32 bank)48 static void oki_bankswitch(INT32 chip, INT32 bank)
49 {
50 	UINT8 *rom = (chip) ? NMK004OKIROM1 : NMK004OKIROM0;
51 
52 	bankdata[chip] = bank;
53 	bank = (bank + 1) & 3;
54 
55 	memcpy (rom + 0x20000, rom + 0x20000 + bank * 0x20000, 0x20000);
56 }
57 
nmk004_tlcs90_write(UINT32 address,UINT8 data)58 static void nmk004_tlcs90_write(UINT32 address, UINT8 data)
59 {
60 	if (address >= 0xfec0 && address < 0xffc0) {	// internal ram
61 		ram[0x800 + (address - 0xfec0)] = data;
62 		return;
63 	}
64 
65 	switch (address)
66 	{
67 		case 0xf800:
68 		case 0xf801:
69 			BurnYM2203Write(0, address & 1, data);
70 		return;
71 
72 		case 0xf900:
73 			MSM6295Write(0, data);
74 		return;
75 
76 		case 0xfa00:
77 			MSM6295Write(1, data);
78 		return;
79 
80 		case 0xfc00:
81 			to_main = data;
82 		return;
83 
84 		case 0xfc01:
85 			oki_bankswitch(0, data);
86 		return;
87 
88 		case 0xfc02:
89 			oki_bankswitch(1, data);
90 		return;
91 	}
92 }
93 
nmk004_tlcs90_write_port(UINT16 port,UINT8 data)94 static void nmk004_tlcs90_write_port(UINT16 port, UINT8 data)
95 {
96 	switch (port)
97 	{
98 		case 0xffc8: { // hack - disable watchdog function
99 			if (data & 1) {
100 		//		SekReset();
101 		//		bprintf (0, _T("Resetting 68k!\n"));
102 			} else {
103 		//		bprintf (0, _T("Clear 68k reset!\n"));
104 			}
105 		}
106 	}
107 }
108 
NMK004_reset()109 void NMK004_reset()
110 {
111 	memset (ram, 0, 0x900);
112 
113 	tlcs90Open(0);
114 	tlcs90Reset();
115 	BurnYM2203Reset();
116 	tlcs90Close();
117 
118 	MSM6295Reset();
119 
120 	oki_bankswitch(0,0);
121 	oki_bankswitch(1,0);
122 	to_main = 0;
123 	to_nmk004 = 0;
124 }
125 
NMK004YM2203IrqHandler(INT32,INT32 nStatus)126 static void NMK004YM2203IrqHandler(INT32, INT32 nStatus)
127 {
128 	tlcs90SetIRQLine(0, (nStatus) ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
129 }
130 
NMK004_init()131 void NMK004_init()
132 {
133 	nmk004_initted = 1;
134 	ram = (UINT8*)BurnMalloc(0x900);
135 
136 	tlcs90Init(0, 8000000);
137 	tlcs90Open(0);
138 	tlcs90MapMemory(NMK004PROGROM, 0x0000, 0xefff, MAP_ROM);
139 	tlcs90MapMemory(ram,	       0xf000, 0xf7ff, MAP_RAM);
140 	tlcs90SetReadHandler(nmk004_tlcs90_read);
141 	tlcs90SetWriteHandler(nmk004_tlcs90_write);
142 	tlcs90SetWritePortHandler(nmk004_tlcs90_write_port);
143 	tlcs90Close();
144 
145 	BurnYM2203Init(1, 1500000, &NMK004YM2203IrqHandler, 0);
146 	BurnTimerAttachTlcs90(8000000);
147 	/* reminder: these route#s are opposite of MAME, for example:
148 	MCFG_SOUND_ROUTE(0, "mono", 0.50)
149 	MCFG_SOUND_ROUTE(1, "mono", 0.50)
150 	MCFG_SOUND_ROUTE(2, "mono", 0.50)
151 	MCFG_SOUND_ROUTE(3, "mono", 1.20)
152 	Is equal to the 4 route lines below. -dink
153 	*/
154 	BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE,   1.20, BURN_SND_ROUTE_BOTH);
155 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.50, BURN_SND_ROUTE_BOTH);
156 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.50, BURN_SND_ROUTE_BOTH);
157 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 0.50, BURN_SND_ROUTE_BOTH);
158 
159 	MSM6295Init(0, 4000000 / 165, 1);
160 	MSM6295Init(1, 4000000 / 165, 1);
161 	MSM6295SetRoute(0, 0.10, BURN_SND_ROUTE_BOTH);
162 	MSM6295SetRoute(1, 0.10, BURN_SND_ROUTE_BOTH);
163 }
164 
NMK004_exit()165 void NMK004_exit()
166 {
167 	if (!nmk004_initted) return;
168 
169 	nmk004_initted = 0;
170 
171 	BurnFree(ram);
172 	ram = NULL;
173 
174 	tlcs90Exit();
175 	BurnYM2203Exit();
176 	MSM6295Exit();
177 }
178 
NMK004Scan(INT32 nAction,INT32 * pnMin)179 INT32 NMK004Scan(INT32 nAction, INT32 *pnMin)
180 {
181 	struct BurnArea ba;
182 
183 	if (nAction & ACB_VOLATILE) {
184 		memset(&ba, 0, sizeof(ba));
185 
186 		ba.Data	  = ram;
187 		ba.nLen	  = 0x900;
188 		ba.szName = "tlcs90 ram";
189 		BurnAcb(&ba);
190 
191 		tlcs90Scan(nAction);
192 
193 		BurnYM2203Scan(nAction, pnMin);
194 		MSM6295Scan(nAction, pnMin);
195 
196 		SCAN_VAR(to_nmk004);
197 		SCAN_VAR(to_main);
198 		SCAN_VAR(bankdata[0]);
199 		SCAN_VAR(bankdata[1]);
200 	}
201 
202 	if (nAction & ACB_WRITE)
203 	{
204 		oki_bankswitch(0,bankdata[0]);
205 		oki_bankswitch(1,bankdata[1]);
206 	}
207 
208 	return 0;
209 }
210 
NMK004NmiWrite(INT32 data)211 void NMK004NmiWrite(INT32 data)
212 {
213 	data ^= 0xff; // hack - no game works properly without this being inverted.
214 
215 	tlcs90SetIRQLine(0x20 /*nmi*/, (data & 1) ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
216 }
217 
NMK004Write(INT32,INT32 data)218 void NMK004Write(INT32, INT32 data)
219 {
220 	to_nmk004 = data & 0xff;
221 }
222 
NMK004Read()223 UINT8 NMK004Read()
224 {
225 	return to_main;
226 }
227