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