1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /*****************************************************************************
4 
5   SunPlus "GCM394" (based on die pictures)
6 
7   Note, these are all the same chip but in different configurations so
8   should be tidied up and made to use callbacks
9 
10 **********************************************************************/
11 
12 #include "emu.h"
13 #include "generalplus_gpl16250soc.h"
14 
15 
16 #define LOG_GCM394_SPI            (1U << 5)
17 #define LOG_GCM394_IO             (1U << 4)
18 #define LOG_GCM394_SYSDMA         (1U << 3)
19 #define LOG_GCM394                (1U << 2)
20 #define LOG_GCM394_UNMAPPED       (1U << 1)
21 
22 #define VERBOSE             (LOG_GCM394 | LOG_GCM394_IO | LOG_GCM394_UNMAPPED | LOG_GCM394_SYSDMA)
23 #include "logmacro.h"
24 
25 
26 DEFINE_DEVICE_TYPE(GCM394, sunplus_gcm394_device, "gcm394", "GeneralPlus GPL16250 System-on-a-Chip")
27 
sunplus_gcm394_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)28 sunplus_gcm394_device::sunplus_gcm394_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
29 	sunplus_gcm394_base_device(mconfig, GCM394, tag, owner, clock)
30 {
31 }
32 
33 DEFINE_DEVICE_TYPE(GPAC800, generalplus_gpac800_device, "gpac800", "GeneralPlus GPL16250 System-on-a-Chip (with NAND handling)")
34 
generalplus_gpac800_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)35 generalplus_gpac800_device::generalplus_gpac800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
36 	sunplus_gcm394_base_device(mconfig, GPAC800, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpac800_device::gpac800_internal_map), this))
37 {
38 }
39 
40 
41 DEFINE_DEVICE_TYPE(GP_SPISPI, generalplus_gpspispi_device, "gpac800spi", "GeneralPlus GPL16250 (with SPI handling)")
42 
generalplus_gpspispi_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)43 generalplus_gpspispi_device::generalplus_gpspispi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
44 	sunplus_gcm394_base_device(mconfig, GP_SPISPI, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpspispi_device::gpspispi_internal_map), this))
45 {
46 }
47 
48 
default_cs_callback(uint16_t cs0,uint16_t cs1,uint16_t cs2,uint16_t cs3,uint16_t cs4)49 void sunplus_gcm394_base_device::default_cs_callback(uint16_t cs0, uint16_t cs1, uint16_t cs2, uint16_t cs3, uint16_t cs4)
50 {
51 	logerror("callback not hooked\n");
52 }
53 
54 
55 // **************************************** SYSTEM DMA device *************************************************
56 
read_dma_params(int channel,int offset)57 uint16_t sunplus_gcm394_base_device::read_dma_params(int channel, int offset)
58 {
59 	uint16_t retdata = m_dma_params[offset][channel];
60 	LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata);
61 	return retdata;
62 }
63 
write_dma_params(int channel,int offset,uint16_t data)64 void sunplus_gcm394_base_device::write_dma_params(int channel, int offset, uint16_t data)
65 {
66 	LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data);
67 
68 	m_dma_params[offset][channel] = data;
69 
70 	// TODO: very likely DMA happens whenever the length is not 0, as long as it's been enabled previously
71 	// jak_prft doesn't rewrite the offset 0 register between requests, and instead writes the length
72 	// as the final thing for each new request.  other games do not write the length last, but turn off
73 	// register 0 before writing params, and enable it again afterwards
74 	// if that's the case, this code can be refactored to work on 'length' instead of the m_dma_latched
75 
76 	if (offset == 3)
77 	{
78 		m_dma_latched[channel] = true;
79 
80 		if (m_dma_params[0][channel] & 1)
81 			trigger_systemm_dma(channel);
82 	}
83 
84 	if (offset == 0 && (data & 1))
85 	{
86 		if (m_dma_latched[channel])
87 			trigger_systemm_dma(channel);
88 	}
89 
90 }
91 
92 
system_dma_params_channel0_r(offs_t offset)93 uint16_t sunplus_gcm394_base_device::system_dma_params_channel0_r(offs_t offset)
94 {
95 	return read_dma_params(0, offset);
96 }
97 
98 
system_dma_params_channel0_w(offs_t offset,uint16_t data)99 void sunplus_gcm394_base_device::system_dma_params_channel0_w(offs_t offset, uint16_t data)
100 {
101 	write_dma_params(0, offset, data);
102 }
103 
system_dma_params_channel1_r(offs_t offset)104 uint16_t sunplus_gcm394_base_device::system_dma_params_channel1_r(offs_t offset)
105 {
106 	return read_dma_params(1, offset);
107 }
108 
system_dma_params_channel1_w(offs_t offset,uint16_t data)109 void sunplus_gcm394_base_device::system_dma_params_channel1_w(offs_t offset, uint16_t data)
110 {
111 	write_dma_params(1, offset, data);
112 }
113 
system_dma_params_channel2_r(offs_t offset)114 uint16_t sunplus_gcm394_base_device::system_dma_params_channel2_r(offs_t offset)
115 {
116 	return read_dma_params(2, offset);
117 }
118 
system_dma_params_channel2_w(offs_t offset,uint16_t data)119 void sunplus_gcm394_base_device::system_dma_params_channel2_w(offs_t offset, uint16_t data)
120 {
121 	write_dma_params(2, offset, data);
122 }
123 
system_dma_params_channel3_r(offs_t offset)124 uint16_t sunplus_gcm394_base_device::system_dma_params_channel3_r(offs_t offset)
125 {
126 	return read_dma_params(3, offset);
127 }
128 
system_dma_params_channel3_w(offs_t offset,uint16_t data)129 void sunplus_gcm394_base_device::system_dma_params_channel3_w(offs_t offset, uint16_t data)
130 {
131 	write_dma_params(3, offset, data);
132 }
133 
134 
135 
136 
system_dma_status_r()137 uint16_t sunplus_gcm394_base_device::system_dma_status_r()
138 {
139 	LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context());
140 
141 	// bit 0 = channel 0 ready
142 	// bit 1 = channel 1 ready
143 
144 	return 0x00ff;
145 }
146 
trigger_systemm_dma(int channel)147 void sunplus_gcm394_base_device::trigger_systemm_dma(int channel)
148 {
149 	uint16_t mode = m_dma_params[0][channel];
150 	uint32_t source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16);
151 	uint32_t dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ;
152 	uint32_t length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16);
153 	int sourcedelta = 0;
154 	int destdelta = 0;
155 
156 	if ((mode & 0xa0) == 0x00)
157 		sourcedelta = 1;
158 	else if ((mode & 0xa0) == 0x20)
159 		sourcedelta = -1;
160 
161 	if ((mode & 0x50) == 0x00)
162 		destdelta = 1;
163 	else if ((mode & 0x50) == 0x10)
164 		destdelta = -1;
165 
166 	LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words) while csbank is %02x\n", machine().describe_context().c_str(), mode, source, dest, length, m_membankswitch_7810 );
167 
168 	// wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set
169 
170 	source &= 0x0fffffff;
171 	length &= 0x0fffffff; // gormiti
172 
173 	for (int i = 0; i < length; i++)
174 	{
175 		uint16_t val;
176 		if (mode & 0x1000)
177 		{
178 			val = (read_space(source) & 0xFF) | (read_space(source) << 8);
179 			i++;
180 		}
181 		else
182 		{
183 			val = read_space(source);
184 		}
185 
186 		source += sourcedelta;
187 
188 		if (mode & 0x2000)
189 		{
190 			write_space(dest, val & 0xFF);
191 			dest += destdelta;
192 			write_space(dest, val >> 8);
193 		}
194 		else
195 		{
196 			write_space(dest, val);
197 		}
198 
199 		dest += destdelta;
200 	}
201 
202 	// HACKS to get into service mode for debugging
203 
204 	// note, these patch the code copied to SRAM so the 'PROGRAM ROM' check fails (it passes otherwise)
205 
206 	address_space& mem = this->space(AS_PROGRAM);
207 
208 	//if (mem.read_word(0x4368c) == 0x4846)
209 	//  mem.write_word(0x4368c, 0x4840);    // cars 2 force service mode
210 
211 	//if (mem.read_word(0x34410) == 0x4846)
212 	//  mem.write_word(0x34410, 0x4840);    // golden tee force service mode
213 
214 	// what is it waiting for when we need these? (needed on some service mode screens)
215 	//if (mem.read_word(0x3f368) == 0x4840)
216 	//  mem.write_word(0x3f368, 0x4841);    // cars 2 IRQ? wait hack
217 
218 	//if (mem.read_word(0x4d8d4) == 0x4840)
219 	//  mem.write_word(0x4d8d4, 0x4841);    // golden tee IRQ? wait hack
220 
221 	//if (mem.read_word(0x3510f) == 0x4845)
222 	//  mem.write_word(0x3510f, 0x4840);    // camp rock force service mode
223 
224 	if (mem.read_word(0x4abe7) == 0x4840)
225 		mem.write_word(0x4abe7, 0x4841);    // camp rock IRQ? wait hack
226 
227 
228 
229 	// clear params after operation
230 	m_dma_params[0][channel] = m_dma_params[0][channel] & 0x00f7;
231 
232 	m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000;
233 	m_dma_latched[channel] = false;
234 
235 	//machine().debug_break();
236 
237 }
238 
system_dma_7abf_unk_w(uint16_t data)239 void sunplus_gcm394_base_device::system_dma_7abf_unk_w(uint16_t data)
240 {
241 	// if this isn't trigger, is it enable? (which could maybe used as similar if DMA only starts to happen if unmasked?)
242 
243 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_7abf_unk_w %04x\n", machine().describe_context(), data);
244 }
245 
system_dma_memtype_r()246 uint16_t sunplus_gcm394_base_device::system_dma_memtype_r()
247 {
248 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context());
249 	return m_system_dma_memtype;
250 }
251 
system_dma_memtype_w(uint16_t data)252 void sunplus_gcm394_base_device::system_dma_memtype_w(uint16_t data)
253 {
254 	static char const* const types[16] =
255 	{
256 		"Unused / USB",
257 		"DAC CHA",
258 		"UART TX",
259 		"UART RX",
260 		"SD/MMC",
261 		"NAND Flash",
262 		"Serial Interface",
263 		"DAC CHB",
264 		"ADC Audo Sample Full",
265 		"SPI TX",
266 		"SPI RX",
267 		"RESERVED (c)",
268 		"RESERVED (d)",
269 		"RESERVED (e)",
270 		"RESERVED (f)"
271 	};
272 
273 	m_system_dma_memtype = data;
274 
275 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x (CH3: %s | CH2: %s | CH1: %s | CH0: %s )\n", machine().describe_context(), data,
276 		types[((m_system_dma_memtype>>12)&0xf)],
277 		types[((m_system_dma_memtype>>8)&0xf)],
278 		types[((m_system_dma_memtype>>4)&0xf)],
279 		types[((m_system_dma_memtype)&0xf)]);
280 
281 }
282 
system_7a35_r()283 uint16_t sunplus_gcm394_base_device::system_7a35_r()
284 {
285 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a35_r\n", machine().describe_context());
286 	return machine().rand();
287 }
288 
system_7a37_r()289 uint16_t sunplus_gcm394_base_device::system_7a37_r()
290 {
291 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a37_r\n", machine().describe_context());
292 	return machine().rand();
293 }
294 
system_7a39_r()295 uint16_t sunplus_gcm394_base_device::system_7a39_r()
296 {
297 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a39_r\n", machine().describe_context());
298 	return machine().rand();
299 }
300 
301 
system_7a3a_r()302 uint16_t sunplus_gcm394_base_device::system_7a3a_r()
303 {
304 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a3a_r\n", machine().describe_context());
305 	return machine().rand();
306 }
307 
system_7a46_r()308 uint16_t sunplus_gcm394_base_device::system_7a46_r()
309 {
310 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a46_r\n", machine().describe_context());
311 	return machine().rand();
312 }
313 
system_7a54_r()314 uint16_t sunplus_gcm394_base_device::system_7a54_r()
315 {
316 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a54_r\n", machine().describe_context());
317 	return machine().rand();
318 }
319 
320 // **************************************** 78xx region with some handling *************************************************
321 
unkarea_780f_status_r()322 uint16_t sunplus_gcm394_base_device::unkarea_780f_status_r()
323 {
324 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_780f_status_r\n", machine().describe_context());
325 	return 0x0002;
326 }
327 
unkarea_78fb_status_r()328 uint16_t sunplus_gcm394_base_device::unkarea_78fb_status_r()
329 {
330 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78fb_status_r\n", machine().describe_context());
331 	m_78fb ^= 0x0100; // status flag for something?
332 	return m_78fb;
333 }
334 
335 // sets bit 0x0002 then expects it to have cleared
unkarea_7819_r()336 uint16_t sunplus_gcm394_base_device::unkarea_7819_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7819_r\n", machine().describe_context()); return m_7819 & ~ 0x0002; }
unkarea_7819_w(uint16_t data)337 void sunplus_gcm394_base_device::unkarea_7819_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7819_w %04x\n", machine().describe_context(), data); m_7819 = data; }
338 
339 // ****************************************  78xx region stubs *************************************************
340 
unkarea_782d_r()341 uint16_t sunplus_gcm394_base_device::unkarea_782d_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_r\n", machine().describe_context()); return m_782d; }
unkarea_782d_w(uint16_t data)342 void sunplus_gcm394_base_device::unkarea_782d_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_w %04x\n", machine().describe_context(), data); m_782d = data; }
343 
unkarea_7803_r()344 uint16_t sunplus_gcm394_base_device::unkarea_7803_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_r\n", machine().describe_context()); return m_7803; }
unkarea_7803_w(uint16_t data)345 void sunplus_gcm394_base_device::unkarea_7803_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_w %04x\n", machine().describe_context(), data); m_7803 = data; }
346 
unkarea_7807_w(uint16_t data)347 void sunplus_gcm394_base_device::unkarea_7807_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7807_w %04x\n", machine().describe_context(), data); m_7807 = data; }
348 
waitmode_enter_780c_w(uint16_t data)349 void sunplus_gcm394_base_device::waitmode_enter_780c_w(uint16_t data)
350 {
351 	// LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::waitmode_enter_780c_w %04x\n", machine().describe_context(), data);
352 	// must be followed by 6 nops to ensure wait mode is entered
353 }
354 
355 // this gets stored / modified / restored before certain memory accesses (
356 // used extensively during SDRAM checks in jak_gtg and jak_car2
357 
membankswitch_7810_r()358 uint16_t sunplus_gcm394_base_device::membankswitch_7810_r()
359 {
360 //  LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::membankswitch_7810_r\n", machine().describe_context());
361 	return m_membankswitch_7810;
362 }
363 
membankswitch_7810_w(uint16_t data)364 void sunplus_gcm394_base_device::membankswitch_7810_w(uint16_t data)
365 {
366 //  if (m_membankswitch_7810 != data)
367 //  LOGMASKED(LOG_GCM394,"%s:sunplus_gcm394_base_device::membankswitch_7810_w %04x\n", machine().describe_context(), data);
368 
369 //  if (m_membankswitch_7810 != data)
370 //      popmessage("bankswitch %04x -> %04x", m_membankswitch_7810, data);
371 
372 	m_membankswitch_7810 = data;
373 }
374 
375 
unkarea_7816_w(uint16_t data)376 void sunplus_gcm394_base_device::unkarea_7816_w(uint16_t data)
377 {
378 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7816_w %04x\n", machine().describe_context(), data);
379 	m_7816 = data;
380 }
381 
unkarea_7817_w(uint16_t data)382 void sunplus_gcm394_base_device::unkarea_7817_w(uint16_t data)
383 {
384 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7817_w %04x\n", machine().describe_context(), data);
385 	m_7817 = data;
386 }
387 
chipselect_csx_memory_device_control_w(offs_t offset,uint16_t data)388 void sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w(offs_t offset, uint16_t data)
389 {
390 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w %04x (782x registers offset %d)\n", machine().describe_context(), data, offset);
391 	m_782x[offset] = data;
392 
393 
394 	static const char* const md[] =
395 	{
396 		"(00) ROM / SRAM",
397 		"(01) ROM / SRAM",
398 		"(10) NOR FLASH",
399 		"(11) NAND FLASH",
400 	};
401 
402 	uint8_t cs_wait =  data & 0x000f;
403 	uint8_t cs_warat = (data & 0x0030)>>4;
404 	uint8_t cs_md    = (data & 0x00c0)>>6;
405 	int cs_size  = (data & 0xff00)>>8;
406 
407 	logerror("CS%d set to size: %02x (%08x words) md: %01x %s   warat: %01x wait: %01x\n", offset, cs_size, (cs_size+1)*0x10000, cs_md, md[cs_md], cs_warat, cs_wait);
408 
409 
410 	m_cs_callback(m_782x[0], m_782x[1], m_782x[2], m_782x[3], m_782x[4]);
411 
412 }
413 
device_post_load()414 void sunplus_gcm394_base_device::device_post_load()
415 {
416 	m_cs_callback(m_782x[0], m_782x[1], m_782x[2], m_782x[3], m_782x[4]);
417 }
418 
unkarea_7835_w(uint16_t data)419 void sunplus_gcm394_base_device::unkarea_7835_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7835_w %04x\n", machine().describe_context(), data); m_7835 = data; }
420 
421 // IO here?
422 
423 // Port A
424 
ioarea_7860_porta_r()425 uint16_t sunplus_gcm394_base_device::ioarea_7860_porta_r()
426 {
427 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7860_porta_r\n", machine().describe_context());
428 	return m_porta_in();
429 }
430 
ioarea_7860_porta_w(uint16_t data)431 void sunplus_gcm394_base_device::ioarea_7860_porta_w(uint16_t data)
432 {
433 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7860_porta_w %04x\n", machine().describe_context(), data);
434 	if (m_porta_out)
435 		m_porta_out(data);
436 }
437 
ioarea_7861_porta_buffer_r()438 uint16_t sunplus_gcm394_base_device::ioarea_7861_porta_buffer_r()
439 {
440 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7861_porta_buffer_r\n", machine().describe_context());
441 	return 0x0000;// 0xffff;// m_7861;
442 }
443 
ioarea_7861_porta_buffer_w(uint16_t data)444 void sunplus_gcm394_base_device::ioarea_7861_porta_buffer_w(uint16_t data)
445 {
446 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7861_porta_buffer_w %04x\n", machine().describe_context(), data);
447 }
448 
ioarea_7862_porta_direction_r()449 uint16_t sunplus_gcm394_base_device::ioarea_7862_porta_direction_r()
450 {
451 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7862_porta_direction_r\n", machine().describe_context());
452 	return m_7862_porta_direction;
453 }
454 
ioarea_7862_porta_direction_w(uint16_t data)455 void sunplus_gcm394_base_device::ioarea_7862_porta_direction_w(uint16_t data)
456 {
457 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7862_porta_direction_w %04x\n", machine().describe_context(), data);
458 	m_7862_porta_direction = data;
459 }
460 
ioarea_7863_porta_attribute_r()461 uint16_t sunplus_gcm394_base_device::ioarea_7863_porta_attribute_r()
462 {
463 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7863_porta_attribute_r\n", machine().describe_context());
464 	return m_7863_porta_attribute;
465 }
466 
ioarea_7863_porta_attribute_w(uint16_t data)467 void sunplus_gcm394_base_device::ioarea_7863_porta_attribute_w(uint16_t data)
468 {
469 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7863_porta_attribute_w %04x\n", machine().describe_context(), data);
470 	m_7863_porta_attribute = data;
471 }
472 
473 // Port B
474 
ioarea_7868_portb_r()475 uint16_t sunplus_gcm394_base_device::ioarea_7868_portb_r()
476 {
477 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7868_portb_r\n", machine().describe_context());
478 	return m_portb_in();
479 }
480 
ioarea_7869_portb_buffer_r()481 uint16_t sunplus_gcm394_base_device::ioarea_7869_portb_buffer_r()
482 {
483 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7869_portb_buffer_r\n", machine().describe_context());
484 	return machine().rand();
485 }
486 
ioarea_7869_portb_buffer_w(uint16_t data)487 void sunplus_gcm394_base_device::ioarea_7869_portb_buffer_w(uint16_t data)
488 {
489 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7869_portb_buffer_w %04x\n", machine().describe_context(), data);
490 }
491 
ioarea_7868_portb_w(uint16_t data)492 void sunplus_gcm394_base_device::ioarea_7868_portb_w(uint16_t data)
493 {
494 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7868_portb_w %04x\n", machine().describe_context(), data);
495 	if (m_portb_out)
496 		m_portb_out(data);
497 }
498 
ioarea_786a_portb_direction_r()499 uint16_t sunplus_gcm394_base_device::ioarea_786a_portb_direction_r()
500 {
501 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_786a_portb_direction_r\n", machine().describe_context());
502 	return m_786a_portb_direction;
503 }
504 
ioarea_786a_portb_direction_w(uint16_t data)505 void sunplus_gcm394_base_device::ioarea_786a_portb_direction_w(uint16_t data)
506 {
507 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_786a_portb_direction_w %04x\n", machine().describe_context(), data);
508 	m_786a_portb_direction = data;
509 }
510 
ioarea_786b_portb_attribute_r()511 uint16_t sunplus_gcm394_base_device::ioarea_786b_portb_attribute_r()
512 {
513 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_786b_portb_attribute_r\n", machine().describe_context());
514 	return m_786b_portb_attribute;
515 }
516 
ioarea_786b_portb_attribute_w(uint16_t data)517 void sunplus_gcm394_base_device::ioarea_786b_portb_attribute_w(uint16_t data)
518 {
519 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_786b_portb_attribute_w %04x\n", machine().describe_context(), data);
520 	m_786b_portb_attribute = data;
521 }
522 
523 // Port C
524 
ioarea_7870_portc_r()525 uint16_t sunplus_gcm394_base_device::ioarea_7870_portc_r()
526 {
527 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7870_portc_r\n", machine().describe_context());
528 	return m_portc_in();
529 }
530 
ioarea_7870_portc_w(uint16_t data)531 void sunplus_gcm394_base_device::ioarea_7870_portc_w(uint16_t data)
532 {
533 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7870_portc_w %04x\n", machine().describe_context(), data);
534 	m_7870 = data;
535 	if (m_portc_out)
536 		m_portc_out(data);
537 }
538 
ioarea_7871_portc_buffer_r()539 uint16_t sunplus_gcm394_base_device::ioarea_7871_portc_buffer_r()
540 {
541 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7871_portc_buffer_r\n", machine().describe_context());
542 	return 0xffff;// m_7871;
543 }
544 
ioarea_7871_portc_buffer_w(uint16_t data)545 void sunplus_gcm394_base_device::ioarea_7871_portc_buffer_w(uint16_t data)
546 {
547 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7871_portc_buffer_w %04x\n", machine().describe_context(), data);
548 }
549 
550 
ioarea_7872_portc_direction_r()551 uint16_t sunplus_gcm394_base_device::ioarea_7872_portc_direction_r()
552 {
553 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7872_portc_direction_r\n", machine().describe_context());
554 	return m_7872_portc_direction;
555 }
556 
ioarea_7872_portc_direction_w(uint16_t data)557 void sunplus_gcm394_base_device::ioarea_7872_portc_direction_w(uint16_t data)
558 {
559 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7872_portc_direction_w %04x\n", machine().describe_context(), data);
560 	m_7872_portc_direction = data;
561 }
562 
ioarea_7873_portc_attribute_r()563 uint16_t sunplus_gcm394_base_device::ioarea_7873_portc_attribute_r()
564 {
565 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7873_portc_attribute_r\n", machine().describe_context());
566 	return m_7873_portc_attribute;
567 }
568 
ioarea_7873_portc_attribute_w(uint16_t data)569 void sunplus_gcm394_base_device::ioarea_7873_portc_attribute_w(uint16_t data)
570 {
571 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7873_portc_attribute_w %04x\n", machine().describe_context(), data);
572 	m_7873_portc_attribute = data;
573 }
574 
575 // Port D
576 
ioarea_7878_portd_r()577 uint16_t sunplus_gcm394_base_device::ioarea_7878_portd_r()
578 {
579 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7878_portd_r\n", machine().describe_context());
580 	return m_portd_in();
581 }
582 
ioarea_7878_portd_w(uint16_t data)583 void sunplus_gcm394_base_device::ioarea_7878_portd_w(uint16_t data)
584 {
585 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7878_portd_w %04x\n", machine().describe_context(), data);
586 	//m_7878 = data;
587 
588 	if (m_portd_out)
589 		m_portd_out(data);
590 }
591 
ioarea_7879_portd_buffer_r()592 uint16_t sunplus_gcm394_base_device::ioarea_7879_portd_buffer_r()
593 {
594 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7879_portd_buffer_r\n", machine().describe_context());
595 	return 0xffff;// m_7871;
596 }
597 
ioarea_7879_portd_buffer_w(uint16_t data)598 void sunplus_gcm394_base_device::ioarea_7879_portd_buffer_w(uint16_t data)
599 {
600 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_7879_portd_buffer_w %04x\n", machine().describe_context(), data);
601 }
602 
603 
ioarea_787a_portd_direction_r()604 uint16_t sunplus_gcm394_base_device::ioarea_787a_portd_direction_r()
605 {
606 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_787a_portd_direction_r\n", machine().describe_context());
607 	return m_787a_portd_direction;
608 }
609 
ioarea_787a_portd_direction_w(uint16_t data)610 void sunplus_gcm394_base_device::ioarea_787a_portd_direction_w(uint16_t data)
611 {
612 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_787a_portd_direction_w %04x\n", machine().describe_context(), data);
613 	m_787a_portd_direction = data;
614 }
615 
ioarea_787b_portd_attribute_r()616 uint16_t sunplus_gcm394_base_device::ioarea_787b_portd_attribute_r()
617 {
618 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_787b_portd_attribute_r\n", machine().describe_context());
619 	return m_787b_portd_attribute;
620 }
621 
ioarea_787b_portd_attribute_w(uint16_t data)622 void sunplus_gcm394_base_device::ioarea_787b_portd_attribute_w(uint16_t data)
623 {
624 	LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioarea_787b_portd_attribute_w %04x\n", machine().describe_context(), data);
625 	m_787b_portd_attribute = data;
626 }
627 
unkarea_7882_r()628 uint16_t sunplus_gcm394_base_device::unkarea_7882_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7882_r\n", machine().describe_context()); return 0xffff;// m_7882;
629 }
unkarea_7882_w(uint16_t data)630 void sunplus_gcm394_base_device::unkarea_7882_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7882_w %04x\n", machine().describe_context(), data); m_7882 = data; }
unkarea_7883_r()631 uint16_t sunplus_gcm394_base_device::unkarea_7883_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7883_r\n", machine().describe_context()); return 0xffff;// m_7883;
632 }
unkarea_7883_w(uint16_t data)633 void sunplus_gcm394_base_device::unkarea_7883_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7883_w %04x\n", machine().describe_context(), data); m_7883 = data; }
634 
unkarea_78a0_w(uint16_t data)635 void sunplus_gcm394_base_device::unkarea_78a0_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a0_w %04x\n", machine().describe_context(), data); m_78a0 = data; }
636 
unkarea_78a0_r()637 uint16_t sunplus_gcm394_base_device::unkarea_78a0_r()
638 {
639 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a0_r\n", machine().describe_context());
640 	return 0x0000;// machine().rand();
641 }
642 
unkarea_78a1_r()643 uint16_t sunplus_gcm394_base_device::unkarea_78a1_r()
644 {
645 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a1_r\n", machine().describe_context());
646 	return 0xffff;// machine().rand();
647 }
648 
unkarea_78a4_w(uint16_t data)649 void sunplus_gcm394_base_device::unkarea_78a4_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a4_w %04x\n", machine().describe_context(), data); m_78a4 = data; }
unkarea_78a5_w(uint16_t data)650 void sunplus_gcm394_base_device::unkarea_78a5_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a5_w %04x\n", machine().describe_context(), data); m_78a5 = data; }
unkarea_78a6_w(uint16_t data)651 void sunplus_gcm394_base_device::unkarea_78a6_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a6_w %04x\n", machine().describe_context(), data); m_78a6 = data; }
652 
unkarea_78a8_w(uint16_t data)653 void sunplus_gcm394_base_device::unkarea_78a8_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a8_w %04x\n", machine().describe_context(), data); m_78a8 = data; }
654 
655 
unkarea_78b0_w(uint16_t data)656 void sunplus_gcm394_base_device::unkarea_78b0_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78b0_w %04x\n", machine().describe_context(), data); m_78b0 = data; }
unkarea_78b1_w(uint16_t data)657 void sunplus_gcm394_base_device::unkarea_78b1_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78b1_w %04x\n", machine().describe_context(), data); m_78b1 = data; }
658 
unkarea_78b2_r()659 uint16_t sunplus_gcm394_base_device::unkarea_78b2_r()
660 {
661 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78b2_r\n", machine().describe_context());
662 	return 0xffff;// m_78b2;
663 }
664 
unkarea_78b2_w(uint16_t data)665 void sunplus_gcm394_base_device::unkarea_78b2_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78b2_w %04x\n", machine().describe_context(), data); m_78b2 = data; }
666 
unkarea_78b8_w(uint16_t data)667 void sunplus_gcm394_base_device::unkarea_78b8_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78b8_w %04x\n", machine().describe_context(), data); m_78b8 = data; }
unkarea_78f0_w(uint16_t data)668 void sunplus_gcm394_base_device::unkarea_78f0_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78f0_w %04x\n", machine().describe_context(), data); m_78f0 = data; }
669 
unkarea_78c0_r()670 uint16_t sunplus_gcm394_base_device::unkarea_78c0_r()
671 {
672 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78c0_r\n", machine().describe_context());
673 	return machine().rand();
674 }
675 
unkarea_78d0_r()676 uint16_t sunplus_gcm394_base_device::unkarea_78d0_r()
677 {
678 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78d0_r\n", machine().describe_context());
679 	return machine().rand();
680 }
681 
unkarea_78d8_r()682 uint16_t sunplus_gcm394_base_device::unkarea_78d8_r()
683 {
684 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78d8_r\n", machine().describe_context());
685 	return machine().rand();
686 }
687 
688 // **************************************** 793x uknown region stubs *************************************************
689 
unkarea_7904_r()690 uint16_t sunplus_gcm394_base_device::unkarea_7904_r()
691 {
692 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7904_r\n", machine().describe_context());
693 	return machine().rand(); // lazertag waits on a bit, status flag for something?
694 
695 }
696 
unkarea_7934_r()697 uint16_t sunplus_gcm394_base_device::unkarea_7934_r()
698 {
699 	// does this return data written, or is it a status flag?
700 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7934_r\n", machine().describe_context());
701 	return m_7934;
702 }
703 
unkarea_7934_w(uint16_t data)704 void sunplus_gcm394_base_device::unkarea_7934_w(uint16_t data)
705 {
706 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7934_w %04x\n", machine().describe_context(), data);
707 	m_7934 = data;
708 }
709 
710 // value of 7935 is read then written in irq6, nothing happens unless bit 0x0100 was set, which could be some kind of irq source being acked?
unkarea_7935_r()711 uint16_t sunplus_gcm394_base_device::unkarea_7935_r()
712 {
713 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7935_r\n", machine().describe_context());
714 	return m_7935;
715 }
716 
unkarea_7935_w(uint16_t data)717 void sunplus_gcm394_base_device::unkarea_7935_w(uint16_t data)
718 {
719 	LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7935_w %04x\n", machine().describe_context(), data);
720 	m_7935 &= ~data;
721 	//checkirq6();
722 }
723 
unkarea_7936_r()724 uint16_t sunplus_gcm394_base_device::unkarea_7936_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7936_r\n", machine().describe_context()); return 0x0000; }
unkarea_7936_w(uint16_t data)725 void sunplus_gcm394_base_device::unkarea_7936_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7936_w %04x\n", machine().describe_context(), data); m_7936 = data; }
726 
727 // **************************************** 794x SPI *************************************************
728 
729 // these are related to the accelerometer values on jak_g500 (8-bit signed) and also the SPI reads for bkrankp
spi_7944_rxdata_r()730 uint16_t sunplus_gcm394_base_device::spi_7944_rxdata_r()
731 {
732 	LOGMASKED(LOG_GCM394_SPI, "%s:sunplus_gcm394_base_device::spi_7944_rxdata_r\n", machine().describe_context());
733 	return machine().rand();
734 }
735 
spi_7945_misc_control_reg_r()736 uint16_t sunplus_gcm394_base_device::spi_7945_misc_control_reg_r()
737 {
738 	LOGMASKED(LOG_GCM394_SPI, "%s:sunplus_gcm394_base_device::spi_7945_misc_control_reg_r\n", machine().describe_context());
739 	return machine().rand();// &0x0007;
740 }
741 
spi_7942_txdata_w(uint16_t data)742 void sunplus_gcm394_base_device::spi_7942_txdata_w(uint16_t data)
743 {
744 	LOGMASKED(LOG_GCM394_SPI, "%s:sunplus_gcm394_base_device::spi_7942_txdata_w %04x\n", machine().describe_context(), data);
745 }
746 
747 // **************************************** 796x unknown *************************************************
748 
unkarea_7960_w(uint16_t data)749 void sunplus_gcm394_base_device::unkarea_7960_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7960_w %04x\n", machine().describe_context(), data); m_7960 = data; }
750 
unkarea_7961_r()751 uint16_t sunplus_gcm394_base_device::unkarea_7961_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_r\n", machine().describe_context()); return m_7961; }
unkarea_7961_w(uint16_t data)752 void sunplus_gcm394_base_device::unkarea_7961_w(uint16_t data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_w %04x\n", machine().describe_context(), data); m_7961 = data; }
753 
754 
755 // **************************************** fallthrough logger etc. *************************************************
756 
unk_r(offs_t offset)757 uint16_t sunplus_gcm394_base_device::unk_r(offs_t offset)
758 {
759 	switch (offset)
760 	{
761 	default:
762 		LOGMASKED(LOG_GCM394_UNMAPPED, "%s:sunplus_gcm394_base_device::unk_r @ 0x%04x\n", machine().describe_context(), offset + 0x7000);
763 		return 0x0000;
764 	}
765 
766 	return 0x0000;
767 }
768 
unk_w(offs_t offset,uint16_t data)769 void sunplus_gcm394_base_device::unk_w(offs_t offset, uint16_t data)
770 {
771 
772 	switch (offset)
773 	{
774 	default:
775 		LOGMASKED(LOG_GCM394_UNMAPPED, "%s:sunplus_gcm394_base_device::unk_w @ 0x%04x (data 0x%04x)\n", machine().describe_context(), offset + 0x7000, data);
776 		break;
777 	}
778 }
779 
base_internal_map(address_map & map)780 void sunplus_gcm394_base_device::base_internal_map(address_map &map)
781 {
782 	map(0x000000, 0x006fff).ram().share("mainram");
783 	map(0x007000, 0x007fff).rw(FUNC(sunplus_gcm394_base_device::unk_r), FUNC(sunplus_gcm394_base_device::unk_w)); // catch unhandled
784 
785 	// ######################################################################################################################################################################################
786 	// 70xx region = video hardware
787 	// ######################################################################################################################################################################################
788 
789 	// note, tilemaps are at the same address offsets in video device as spg2xx (but unknown devices are extra)
790 
791 	map(0x007000, 0x007007).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap2_regs_r), FUNC(gcm394_base_video_device::tmap2_regs_w)); // written with other unknown_video_device1 LSB/MSB regs below (roz layer or line layer?)
792 	map(0x007008, 0x00700f).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap3_regs_r), FUNC(gcm394_base_video_device::tmap3_regs_w)); // written with other unknown_video_device2 LSB/MSB regs below (roz layer or line layer?)
793 
794 	map(0x007010, 0x007015).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_regs_r), FUNC(gcm394_base_video_device::tmap0_regs_w));
795 	map(0x007016, 0x00701b).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_regs_r), FUNC(gcm394_base_video_device::tmap1_regs_w));
796 
797 	map(0x00701c, 0x00701c).w(m_spg_video, FUNC(gcm394_base_video_device::video_701c_w)); // these 3 are written together in paccon
798 	map(0x00701d, 0x00701d).w(m_spg_video, FUNC(gcm394_base_video_device::video_701d_w));
799 	map(0x00701e, 0x00701e).w(m_spg_video, FUNC(gcm394_base_video_device::video_701e_w));
800 
801 	// tilebase LSBs
802 	map(0x007020, 0x007020).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_w));           // tilebase, written with other tmap0 regs
803 	map(0x007021, 0x007021).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_w));           // tilebase, written with other tmap1 regs
804 	map(0x007022, 0x007022).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7022_gfxbase_lsb_r), FUNC(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)); // sprite tilebase written as 7022, 702d and 7042 group
805 	map(0x007023, 0x007023).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap2_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap2_tilebase_lsb_w));           // written with other tmap2 regs (roz layer or line layer?)
806 	map(0x007024, 0x007024).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap3_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap3_tilebase_lsb_w));           // written with other tmap3 regs (roz layer or line layer?)
807 
808 	map(0x00702a, 0x00702a).w(m_spg_video, FUNC(gcm394_base_video_device::video_702a_w)); // blend level control
809 
810 	// tilebase MSBs
811 	map(0x00702b, 0x00702b).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap0_tilebase_msb_w));           // written with other tmap0 regs
812 	map(0x00702c, 0x00702c).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap1_tilebase_msb_w));           // written with other tmap1 regs
813 	map(0x00702d, 0x00702d).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_702d_gfxbase_msb_r), FUNC(gcm394_base_video_device::sprite_702d_gfxbase_msb_w)); // sprites, written as 7022, 702d and 7042 group
814 	map(0x00702e, 0x00702e).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap2_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap2_tilebase_msb_w));           // written with other tmap2 regs (roz layer or line layer?)
815 	map(0x00702f, 0x00702f).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap3_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap3_tilebase_msb_w));           // written with other tmap3 regs (roz layer or line layer?)
816 
817 	map(0x007036, 0x007036).w(m_spg_video, FUNC(gcm394_base_video_device::split_irq_xpos_w));
818 	map(0x007037, 0x007037).w(m_spg_video, FUNC(gcm394_base_video_device::split_irq_ypos_w));
819 
820 
821 	map(0x007030, 0x007030).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7030_brightness_r), FUNC(gcm394_base_video_device::video_7030_brightness_w));
822 	map(0x007038, 0x007038).r(m_spg_video, FUNC(gcm394_base_video_device::video_curline_r));
823 	map(0x00703a, 0x00703a).rw(m_spg_video, FUNC(gcm394_base_video_device::video_703a_palettebank_r), FUNC(gcm394_base_video_device::video_703a_palettebank_w));
824 	map(0x00703c, 0x00703c).rw(m_spg_video, FUNC(gcm394_base_video_device::video_703c_tvcontrol1_r), FUNC(gcm394_base_video_device::video_703c_tvcontrol1_w)); // TV Control 1
825 
826 	map(0x007042, 0x007042).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7042_extra_r), FUNC(gcm394_base_video_device::sprite_7042_extra_w)); // maybe sprites,  written as 7022, 702d and 7042 group
827 
828 	map(0x007051, 0x007051).r(m_spg_video, FUNC(gcm394_base_video_device::video_7051_r)); // wrlshunt checks this (doesn't exist on older SPG?)
829 
830 	map(0x007062, 0x007062).rw(m_spg_video, FUNC(gcm394_base_video_device::videoirq_source_enable_r), FUNC(gcm394_base_video_device::videoirq_source_enable_w));
831 	map(0x007063, 0x007063).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7063_videoirq_source_r), FUNC(gcm394_base_video_device::video_7063_videoirq_source_ack_w));
832 
833 	// note, 70 / 71 / 72 are the same offsets used for DMA as in spg2xx video device
834 	map(0x007070, 0x007070).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_source_w));                                                      // video dma, not system dma? (sets pointers to ram buffers)
835 	map(0x007071, 0x007071).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_dest_w));                                                        // sets pointers to 7300, 7400 ram areas below
836 	map(0x007072, 0x007072).rw(m_spg_video, FUNC(gcm394_base_video_device::video_dma_size_busy_r), FUNC(gcm394_base_video_device::video_dma_size_trigger_w));     //
837 
838 	// these don't exist on older SPG
839 	map(0x00707c, 0x00707c).r(m_spg_video, FUNC(gcm394_base_video_device::video_707c_r)); // wrlshunt polls this waiting for 0x8000, is this some kind of manual port-based data upload?
840 
841 	map(0x00707e, 0x00707e).w(m_spg_video, FUNC(gcm394_base_video_device::video_707e_spritebank_w));                                                         // written around same time as DMA, seems to select alt sprite bank
842 	map(0x00707f, 0x00707f).rw(m_spg_video, FUNC(gcm394_base_video_device::video_707f_r), FUNC(gcm394_base_video_device::video_707f_w));
843 
844 	// another set of registers for something?
845 	map(0x007080, 0x007080).w(m_spg_video, FUNC(gcm394_base_video_device::video_7080_w));
846 	map(0x007081, 0x007081).w(m_spg_video, FUNC(gcm394_base_video_device::video_7081_w));
847 	map(0x007082, 0x007082).w(m_spg_video, FUNC(gcm394_base_video_device::video_7082_w));
848 	map(0x007083, 0x007083).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7083_r), FUNC(gcm394_base_video_device::video_7083_w));
849 	map(0x007084, 0x007084).w(m_spg_video, FUNC(gcm394_base_video_device::video_7084_w));
850 	map(0x007085, 0x007085).w(m_spg_video, FUNC(gcm394_base_video_device::video_7085_w));
851 	map(0x007086, 0x007086).w(m_spg_video, FUNC(gcm394_base_video_device::video_7086_w));
852 	map(0x007087, 0x007087).w(m_spg_video, FUNC(gcm394_base_video_device::video_7087_w));
853 	map(0x007088, 0x007088).w(m_spg_video, FUNC(gcm394_base_video_device::video_7088_w));
854 
855 	map(0x0070e0, 0x0070e0).r(m_spg_video, FUNC(gcm394_base_video_device::video_70e0_r)); // gormiti checks this
856 
857 	// ######################################################################################################################################################################################
858 	// 73xx-77xx = video ram
859 	// ######################################################################################################################################################################################
860 
861 	map(0x007100, 0x0071ff).ram().share("rowscroll"); // based on jak_s500
862 	map(0x007200, 0x0072ff).ram().share("rowzoom"); // ^^
863 
864 	map(0x007300, 0x0073ff).rw(m_spg_video, FUNC(gcm394_base_video_device::palette_r), FUNC(gcm394_base_video_device::palette_w));
865 
866 	map(0x007400, 0x0077ff).rw(m_spg_video, FUNC(gcm394_base_video_device::spriteram_r), FUNC(gcm394_base_video_device::spriteram_w));
867 
868 	// ######################################################################################################################################################################################
869 	// 78xx region = system regs?
870 	// ######################################################################################################################################################################################
871 
872 	map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::unkarea_7803_r), FUNC(sunplus_gcm394_base_device::unkarea_7803_w));
873 
874 	map(0x007807, 0x007807).w(FUNC(sunplus_gcm394_base_device::unkarea_7807_w));
875 	// 7808
876 
877 	// 780a
878 
879 	map(0x00780c, 0x00780c).w(FUNC(sunplus_gcm394_base_device::waitmode_enter_780c_w));
880 
881 	map(0x00780f, 0x00780f).r(FUNC(sunplus_gcm394_base_device::unkarea_780f_status_r));
882 
883 	map(0x007810, 0x007810).rw(FUNC(sunplus_gcm394_base_device::membankswitch_7810_r), FUNC(sunplus_gcm394_base_device::membankswitch_7810_w));  // 7810 Bank Switch Control Register  (P_BankSwitch_Ctrl) (maybe)
884 
885 	map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::unkarea_7819_r), FUNC(sunplus_gcm394_base_device::unkarea_7819_w));
886 
887 	map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w));
888 	map(0x007817, 0x007817).w(FUNC(sunplus_gcm394_base_device::unkarea_7817_w));
889 
890 	// ######################################################################################################################################################################################
891 	// 782x region = memory config / control
892 	// ######################################################################################################################################################################################
893 																										 // wrlshunt                                                               | smartfp
894 	map(0x007820, 0x007824).w(FUNC(sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w)); // 7f8a (7f8a before DMA from ROM to RAM, 008a after DMA from ROM to RAM) | 3f04      7820 Chip Select (CS0) Memory Device Control (P_MC50_Ctrl)
895 																										 // 7f47                                                                   | 0044      7821 Chip Select (CS1) Memory Device Control (P_MC51_Ctrl)
896 																										 // 0047                                                                   | 1f44      7822 Chip Select (CS2) Memory Device Control (P_MC52_Ctrl)
897 																										 // 0047                                                                   | 0044      7823 Chip Select (CS3) Memory Device Control (P_MC53_Ctrl)
898 																										 // 0047                                                                   | 0044      7824 Chip Select (CS4) Memory Device Control (P_MC54_Ctrl)
899 
900 	map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::unkarea_782d_r), FUNC(sunplus_gcm394_base_device::unkarea_782d_w)); // on startup
901 	// 782f
902 
903 	map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::unkarea_7835_w));
904 
905 	// 783a
906 	// 783b
907 	// 783c
908 	// 783d
909 	// 783e
910 
911 	// 7840 - accessed by code in RAM when changing bank in tkmag220
912 	// 7841 - ^^
913 
914 	// ######################################################################################################################################################################################
915 	// 786x - 787x - IO related?
916 	// ######################################################################################################################################################################################
917 
918 	map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_r), FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_w)); //    7860  I/O PortA Data Register
919 	map(0x007861, 0x007861).rw(FUNC(sunplus_gcm394_base_device::ioarea_7861_porta_buffer_r), FUNC(sunplus_gcm394_base_device::ioarea_7861_porta_buffer_w)); // 7861  I/O PortA Buffer Register
920 	map(0x007862, 0x007862).rw(FUNC(sunplus_gcm394_base_device::ioarea_7862_porta_direction_r), FUNC(sunplus_gcm394_base_device::ioarea_7862_porta_direction_w));  // 7862  I/O PortA Direction Register
921 	map(0x007863, 0x007863).rw(FUNC(sunplus_gcm394_base_device::ioarea_7863_porta_attribute_r), FUNC(sunplus_gcm394_base_device::ioarea_7863_porta_attribute_w)); //    7863  I/O PortA Attribute Register
922 
923 	map(0x007868, 0x007868).rw(FUNC(sunplus_gcm394_base_device::ioarea_7868_portb_r), FUNC(sunplus_gcm394_base_device::ioarea_7868_portb_w)); // on startup   // 7868  I/O PortB Data Register
924 	map(0x007869, 0x007869).rw(FUNC(sunplus_gcm394_base_device::ioarea_7869_portb_buffer_r), FUNC(sunplus_gcm394_base_device::ioarea_7869_portb_buffer_w)); //  7869  I/O PortB Buffer Register   // jak_s500
925 	map(0x00786a, 0x00786a).rw(FUNC(sunplus_gcm394_base_device::ioarea_786a_portb_direction_r), FUNC(sunplus_gcm394_base_device::ioarea_786a_portb_direction_w)); // 786a  I/O PortB Direction Register
926 	map(0x00786b, 0x00786b).rw(FUNC(sunplus_gcm394_base_device::ioarea_786b_portb_attribute_r), FUNC(sunplus_gcm394_base_device::ioarea_786b_portb_attribute_w)); // 786b  I/O PortB Attribute Register
927 	// 786c  I/O PortB Latch / Wakeup
928 
929 	map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioarea_7870_portc_r) ,FUNC(sunplus_gcm394_base_device::ioarea_7870_portc_w)); // 7870  I/O PortC Data Register
930 	map(0x007871, 0x007871).rw(FUNC(sunplus_gcm394_base_device::ioarea_7871_portc_buffer_r), FUNC(sunplus_gcm394_base_device::ioarea_7871_portc_buffer_w)); // 7871  I/O PortC Buffer Register
931 	map(0x007872, 0x007872).rw(FUNC(sunplus_gcm394_base_device::ioarea_7872_portc_direction_r), FUNC(sunplus_gcm394_base_device::ioarea_7872_portc_direction_w)); // 7872  I/O PortC Direction Register
932 	map(0x007873, 0x007873).rw(FUNC(sunplus_gcm394_base_device::ioarea_7873_portc_attribute_r), FUNC(sunplus_gcm394_base_device::ioarea_7873_portc_attribute_w)); // 7873  I/O PortC Attribute Register
933 
934 	// 7874 (data 0x1249) (bkrankp data 0x36db)
935 
936 	map(0x007878, 0x007878).rw(FUNC(sunplus_gcm394_base_device::ioarea_7878_portd_r) ,FUNC(sunplus_gcm394_base_device::ioarea_7878_portd_w)); // 7878  I/O PortD Data Register
937 	map(0x007879, 0x007879).rw(FUNC(sunplus_gcm394_base_device::ioarea_7879_portd_buffer_r), FUNC(sunplus_gcm394_base_device::ioarea_7879_portd_buffer_w)); // 7879  I/O PortD Buffer Register
938 	map(0x00787a, 0x00787a).rw(FUNC(sunplus_gcm394_base_device::ioarea_787a_portd_direction_r), FUNC(sunplus_gcm394_base_device::ioarea_787a_portd_direction_w)); // 787a  I/O PortD Direction Register
939 	map(0x00787b, 0x00787b).rw(FUNC(sunplus_gcm394_base_device::ioarea_787b_portd_attribute_r), FUNC(sunplus_gcm394_base_device::ioarea_787b_portd_attribute_w)); // 787b  I/O PortD Attribute Register
940 
941 	// 787c (data 0x1249) (bkrankp data 0x36db)
942 	// 787e (data 0x1249) (bkrankp data 0x36db)
943 
944 	// 7880
945 
946 	map(0x007882, 0x007882).rw(FUNC(sunplus_gcm394_base_device::unkarea_7882_r), FUNC(sunplus_gcm394_base_device::unkarea_7882_w));
947 	map(0x007883, 0x007883).rw(FUNC(sunplus_gcm394_base_device::unkarea_7883_r), FUNC(sunplus_gcm394_base_device::unkarea_7883_w));
948 
949 	// 0x7888 (data 0x1249) (bkrankp data 0x36db), written with 7874 / 787c / 787e above
950 
951 	// ######################################################################################################################################################################################
952 	// 78ax - interrupt controller?
953 	// ######################################################################################################################################################################################
954 
955 	map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::unkarea_78a0_r), FUNC(sunplus_gcm394_base_device::unkarea_78a0_w));
956 	map(0x0078a1, 0x0078a1).r(FUNC(sunplus_gcm394_base_device::unkarea_78a1_r));
957 
958 	map(0x0078a4, 0x0078a4).w(FUNC(sunplus_gcm394_base_device::unkarea_78a4_w));
959 	map(0x0078a5, 0x0078a5).w(FUNC(sunplus_gcm394_base_device::unkarea_78a5_w));
960 	map(0x0078a6, 0x0078a6).w(FUNC(sunplus_gcm394_base_device::unkarea_78a6_w));
961 
962 	map(0x0078a8, 0x0078a8).w(FUNC(sunplus_gcm394_base_device::unkarea_78a8_w));
963 
964 	// ######################################################################################################################################################################################
965 	// 78bx - timer control?
966 	// ######################################################################################################################################################################################
967 
968 	map(0x0078b0, 0x0078b0).w(FUNC(sunplus_gcm394_base_device::unkarea_78b0_w));  // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl)
969 	map(0x0078b1, 0x0078b1).w(FUNC(sunplus_gcm394_base_device::unkarea_78b1_w));  // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl)
970 	map(0x0078b2, 0x0078b2).rw(FUNC(sunplus_gcm394_base_device::unkarea_78b2_r), FUNC(sunplus_gcm394_base_device::unkarea_78b2_w));  // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl)
971 
972 	map(0x0078b8, 0x0078b8).w(FUNC(sunplus_gcm394_base_device::unkarea_78b8_w));  // 78b8 TimeBase Counter Reset Register  (P_TimeBase_Reset)
973 
974 	map(0x0078c0, 0x0078c0).r(FUNC(sunplus_gcm394_base_device::unkarea_78c0_r)); // beijuehh
975 
976 	map(0x0078d0, 0x0078d0).r(FUNC(sunplus_gcm394_base_device::unkarea_78d0_r)); // jak_s500
977 	map(0x0078d8, 0x0078d8).r(FUNC(sunplus_gcm394_base_device::unkarea_78d8_r)); // jak_tsh
978 
979 
980 	// ######################################################################################################################################################################################
981 	// 78fx - unknown
982 	// ######################################################################################################################################################################################
983 
984 	map(0x0078f0, 0x0078f0).w(FUNC(sunplus_gcm394_base_device::unkarea_78f0_w));
985 
986 	map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::unkarea_78fb_status_r));
987 
988 	// ######################################################################################################################################################################################
989 	// 793x - misc?
990 	// ######################################################################################################################################################################################
991 
992 	map(0x007904, 0x007904).r(FUNC(sunplus_gcm394_base_device::unkarea_7904_r)); // lazertag after a while
993 
994 	// possible rtc?
995 	map(0x007934, 0x007934).rw(FUNC(sunplus_gcm394_base_device::unkarea_7934_r), FUNC(sunplus_gcm394_base_device::unkarea_7934_w));
996 	map(0x007935, 0x007935).rw(FUNC(sunplus_gcm394_base_device::unkarea_7935_r), FUNC(sunplus_gcm394_base_device::unkarea_7935_w));
997 	map(0x007936, 0x007936).rw(FUNC(sunplus_gcm394_base_device::unkarea_7936_r), FUNC(sunplus_gcm394_base_device::unkarea_7936_w));
998 
999 	// ######################################################################################################################################################################################
1000 	// 794x - SPI
1001 	// ######################################################################################################################################################################################
1002 
1003 	//7940 P_SPI_Ctrl     - SPI Control Register
1004 	//7941 P_SPI_TXStatus - SPI Transmit Status Register
1005 	map(0x007942, 0x007942).w(FUNC(sunplus_gcm394_base_device::spi_7942_txdata_w)); //7942 P_SPI_TXData   - SPI Transmit FIFO Register
1006 	//7943 P_SPI_RXStatus - SPI Receive Status Register
1007 	map(0x007944, 0x007944).r(FUNC(sunplus_gcm394_base_device::spi_7944_rxdata_r));           // 7944 P_SPI_RXData - SPI Receive FIFO Register    (jak_s500 accelerometer)   (also the SPI ROM DMA input port for bkrankp?)
1008 	map(0x007945, 0x007945).r(FUNC(sunplus_gcm394_base_device::spi_7945_misc_control_reg_r)); // 7945 P_SPI_Misc   - SPI Misc Control Register    (jak_s500 accelerometer)
1009 
1010 	// ######################################################################################################################################################################################
1011 	// 796x - unknown
1012 	// ######################################################################################################################################################################################
1013 
1014 	// possible adc?
1015 	map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::unkarea_7960_w));
1016 	map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::unkarea_7961_r), FUNC(sunplus_gcm394_base_device::unkarea_7961_w));
1017 
1018 	// ######################################################################################################################################################################################
1019 	// 7axx region = system (including dma)
1020 	// ######################################################################################################################################################################################
1021 
1022 	map(0x007a35, 0x007a35).r(FUNC(sunplus_gcm394_base_device::system_7a35_r)); // wlsair60
1023 	map(0x007a37, 0x007a37).r(FUNC(sunplus_gcm394_base_device::system_7a37_r)); // wlsair60
1024 	map(0x007a39, 0x007a39).r(FUNC(sunplus_gcm394_base_device::system_7a39_r)); // wlsair60
1025 	map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::system_7a3a_r)); // ?
1026 	map(0x007a46, 0x007a46).r(FUNC(sunplus_gcm394_base_device::system_7a46_r)); // wlsair60
1027 	map(0x007a54, 0x007a54).r(FUNC(sunplus_gcm394_base_device::system_7a54_r)); // wlsair60
1028 
1029 	map(0x007a80, 0x007a87).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_w));
1030 	map(0x007a88, 0x007a8f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_w)); // jak_tsm writes here
1031 	map(0x007a90, 0x007a97).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_w)); // bkrankp writes here (is this on all types or just SPI?)
1032 	map(0x007a98, 0x007a9f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_w)); // not seen, but probably
1033 
1034 	map(0x007abe, 0x007abe).rw(FUNC(sunplus_gcm394_base_device::system_dma_memtype_r), FUNC(sunplus_gcm394_base_device::system_dma_memtype_w)); // 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?)
1035 	map(0x007abf, 0x007abf).rw(FUNC(sunplus_gcm394_base_device::system_dma_status_r), FUNC(sunplus_gcm394_base_device::system_dma_7abf_unk_w));
1036 
1037 	// ######################################################################################################################################################################################
1038 	// 7bxx-7fxx = audio
1039 	// ######################################################################################################################################################################################
1040 
1041 	map(0x007b80, 0x007bbf).rw(m_spg_audio, FUNC(sunplus_gcm394_audio_device::control_r), FUNC(sunplus_gcm394_audio_device::control_w));
1042 	map(0x007c00, 0x007dff).rw(m_spg_audio, FUNC(sunplus_gcm394_audio_device::audio_r), FUNC(sunplus_gcm394_audio_device::audio_w));
1043 	map(0x007e00, 0x007fff).rw(m_spg_audio, FUNC(sunplus_gcm394_audio_device::audio_phase_r), FUNC(sunplus_gcm394_audio_device::audio_phase_w));
1044 
1045 }
1046 
gcm394_internal_map(address_map & map)1047 void sunplus_gcm394_base_device::gcm394_internal_map(address_map& map)
1048 {
1049 	sunplus_gcm394_base_device::base_internal_map(map);
1050 
1051 	// no internal ROM on this model?
1052 
1053 	map(0x08000, 0x0ffff).r(FUNC(sunplus_gcm394_base_device::internalrom_lower32_r)).nopw();
1054 
1055 	map(0x10000, 0x01ffff).nopr();
1056 
1057 	map(0x020000, 0x1fffff).rw(FUNC(sunplus_gcm394_base_device::cs_space_r), FUNC(sunplus_gcm394_base_device::cs_space_w));
1058 	map(0x200000, 0x3fffff).rw(FUNC(sunplus_gcm394_base_device::cs_bank_space_r), FUNC(sunplus_gcm394_base_device::cs_bank_space_w));
1059 }
1060 
cs_space_r(offs_t offset)1061 uint16_t sunplus_gcm394_base_device::cs_space_r(offs_t offset)
1062 {
1063 	return m_cs_space->read_word(offset);
1064 }
1065 
cs_space_w(offs_t offset,uint16_t data)1066 void sunplus_gcm394_base_device::cs_space_w(offs_t offset, uint16_t data)
1067 {
1068 	m_cs_space->write_word(offset, data);
1069 }
cs_bank_space_r(offs_t offset)1070 uint16_t sunplus_gcm394_base_device::cs_bank_space_r(offs_t offset)
1071 {
1072 	int bank = m_membankswitch_7810 & 0x3f;
1073 	int realoffset = offset + (bank * 0x200000) - m_csbase;
1074 
1075 	if (realoffset < 0)
1076 	{
1077 		logerror("read real offset < 0\n");
1078 		return 0;
1079 	}
1080 
1081 	return m_cs_space->read_word(realoffset);
1082 }
1083 
cs_bank_space_w(offs_t offset,uint16_t data)1084 void sunplus_gcm394_base_device::cs_bank_space_w(offs_t offset, uint16_t data)
1085 {
1086 	int bank = m_membankswitch_7810 & 0x3f;
1087 	int realoffset = offset + (bank * 0x200000) - m_csbase;
1088 
1089 	if (realoffset < 0)
1090 	{
1091 		logerror("write real offset < 0\n");
1092 		return;
1093 	}
1094 
1095 	m_cs_space->write_word(realoffset, data);
1096 }
1097 
1098 
1099 
internalrom_lower32_r(offs_t offset)1100 uint16_t sunplus_gcm394_base_device::internalrom_lower32_r(offs_t offset)
1101 {
1102 	if (m_boot_mode == 0)
1103 	{
1104 		uint16_t* introm = (uint16_t*)m_internalrom->base();
1105 		return introm[offset];
1106 	}
1107 	else
1108 	{
1109 		if (!m_cs_space)
1110 			return 0x0000;
1111 
1112 		uint16_t val = m_cs_space->read_word(offset+0x8000);
1113 		return val;
1114 	}
1115 }
1116 
1117 
1118 // GPR27P512A   = C2 76
1119 // HY27UF081G2A = AD F1 80 1D
1120 // H27U518S2C   = AD 76
1121 
nand_7854_r()1122 uint16_t generalplus_gpac800_device::nand_7854_r()
1123 {
1124 	// TODO: use actual NAND / Smart Media devices once this is better understood.
1125 	// The games have extensive checks on startup to determine the flash types, but then it appears that
1126 	// certain games (eg jak_tsm) will only function correctly with specific ones, even if the code
1127 	// continues regardless.  Others will bail early if they don't get what they want.
1128 
1129 	// I think some unSP core maths bugs are causing severe issues after the initial load for jak_tsm
1130 	// at the moment, possibly the same ones that are causing rendering issues in the jak_gtg bitmap
1131 	// test and seemingly incorrect road data for jak_car2, either that or the hookup here is very
1132 	// non-standard outside of the ident codes
1133 
1134 	// real TSM code starts at 4c000
1135 
1136 
1137 	//logerror("%s:sunplus_gcm394_base_device::nand_7854_r\n", machine().describe_context());
1138 
1139 	if (m_nandcommand == 0x90) // read ident
1140 	{
1141 		logerror("%s:sunplus_gcm394_base_device::nand_7854_r   READ IDENT byte %d\n", machine().describe_context(), m_curblockaddr);
1142 
1143 		uint8_t data = 0x00;
1144 
1145 		if (m_romtype == 0)
1146 		{
1147 			if (m_curblockaddr == 0)
1148 				data = 0xc2;
1149 			else
1150 				data = 0x76;
1151 		}
1152 		else if (m_romtype == 1)
1153 		{
1154 			if (m_curblockaddr == 0)
1155 				data = 0xad;
1156 			else if (m_curblockaddr == 1)
1157 				data = 0x76;
1158 		}
1159 		else
1160 		{
1161 			if (m_curblockaddr == 0)
1162 				data = 0xad;
1163 			else if (m_curblockaddr == 1)
1164 				data = 0xf1;
1165 			else if (m_curblockaddr == 2)
1166 				data = 0x80;
1167 			else if (m_curblockaddr == 3)
1168 				data = 0x1d;
1169 		}
1170 
1171 		m_curblockaddr++;
1172 
1173 		return data;
1174 	}
1175 	else if (m_nandcommand == 0x00 || m_nandcommand == 0x01 || m_nandcommand  == 0x50)
1176 	{
1177 		//logerror("%s:sunplus_gcm394_base_device::nand_7854_r   READ DATA byte %d\n", machine().describe_context(), m_curblockaddr);
1178 
1179 		uint8_t data = m_nand_read_cb(m_effectiveaddress + m_curblockaddr);
1180 
1181 		m_curblockaddr++;
1182 
1183 		return data;
1184 	}
1185 	else if (m_nandcommand == 0x70) // read status
1186 	{
1187 		logerror("%s:sunplus_gcm394_base_device::nand_7854_r   READ STATUS byte %d\n", machine().describe_context(), m_curblockaddr);
1188 
1189 		return 0xffff;
1190 	}
1191 	else
1192 	{
1193 		logerror("%s:sunplus_gcm394_base_device::nand_7854_r   READ UNKNOWN byte %d\n", machine().describe_context(), m_curblockaddr);
1194 		return 0xffff;
1195 	}
1196 
1197 	return 0x0000;
1198 }
1199 
1200 // 7998
1201 
nand_command_w(uint16_t data)1202 void generalplus_gpac800_device::nand_command_w(uint16_t data)
1203 {
1204 	logerror("%s:sunplus_gcm394_base_device::nand_command_w %04x\n", machine().describe_context(), data);
1205 	m_nandcommand = data;
1206 }
1207 
nand_addr_low_w(uint16_t data)1208 void generalplus_gpac800_device::nand_addr_low_w(uint16_t data)
1209 {
1210 	logerror("%s:sunplus_gcm394_base_device::nand_addr_low_w %04x\n", machine().describe_context(), data);
1211 	m_nand_addr_low = data;
1212 	m_curblockaddr = 0;
1213 }
1214 
recalculate_calculate_effective_nand_address()1215 void generalplus_gpac800_device::recalculate_calculate_effective_nand_address()
1216 {
1217 	uint8_t type = m_nand_7856 & 0xf;
1218 	uint8_t shift = 0;
1219 	uint32_t page_offset = 0;
1220 
1221 	if (type == 7)
1222 		shift = 4;
1223 	else if (type == 11)
1224 		shift = 5;
1225 
1226 	if (m_nandcommand == 0x01)
1227 		page_offset = 256;
1228 	else if (m_nandcommand == 0x50)
1229 		page_offset = 512;
1230 
1231 	uint32_t nandaddress = (m_nand_addr_high << 16) | m_nand_addr_low;
1232 
1233 	if (m_nand_7850 & 0x4000)
1234 		nandaddress *= 2;
1235 
1236 	uint32_t page = type ? nandaddress : /*(m_nand_7850 & 0x4000) ?*/ nandaddress >> 8 /*: nandaddress >> 9*/;
1237 	m_effectiveaddress = (page * 528 + page_offset) << shift;
1238 
1239 	logerror("%s: Requested address is %08x, translating to %08x\n", machine().describe_context(), nandaddress, m_effectiveaddress);
1240 }
1241 
nand_addr_high_w(uint16_t data)1242 void generalplus_gpac800_device::nand_addr_high_w(uint16_t data)
1243 {
1244 	logerror("%s:sunplus_gcm394_base_device::nand_addr_high_w %04x\n", machine().describe_context(), data);
1245 	m_nand_addr_high = data;
1246 
1247 	recalculate_calculate_effective_nand_address();
1248 
1249 	m_curblockaddr = 0;
1250 }
1251 
nand_dma_ctrl_w(uint16_t data)1252 void generalplus_gpac800_device::nand_dma_ctrl_w(uint16_t data)
1253 {
1254 	logerror("%s:sunplus_gcm394_base_device::nand_dma_ctrl_w(?) %04x\n", machine().describe_context(), data);
1255 	m_nand_dma_ctrl = data;
1256 }
1257 
nand_7850_status_r()1258 uint16_t generalplus_gpac800_device::nand_7850_status_r()
1259 {
1260 	// 0x8000 = ready
1261 	return m_nand_7850 | 0x8000;
1262 }
1263 
nand_7850_w(uint16_t data)1264 void generalplus_gpac800_device::nand_7850_w(uint16_t data)
1265 {
1266 	logerror("%s:sunplus_gcm394_base_device::nand_7850_w %04x\n", machine().describe_context(), data);
1267 	m_nand_7850 = data;
1268 }
1269 
nand_7856_type_w(uint16_t data)1270 void generalplus_gpac800_device::nand_7856_type_w(uint16_t data)
1271 {
1272 	logerror("%s:sunplus_gcm394_base_device::nand_7856_type_w %04x\n", machine().describe_context(), data);
1273 	m_nand_7856 = data;
1274 
1275 	recalculate_calculate_effective_nand_address();
1276 
1277 	m_curblockaddr = 0;
1278 }
1279 
nand_7857_w(uint16_t data)1280 void generalplus_gpac800_device::nand_7857_w(uint16_t data)
1281 {
1282 	logerror("%s:sunplus_gcm394_base_device::nand_7857_w %04x\n", machine().describe_context(), data);
1283 	m_nand_7857 = data;
1284 }
1285 
nand_785b_w(uint16_t data)1286 void generalplus_gpac800_device::nand_785b_w(uint16_t data)
1287 {
1288 	logerror("%s:sunplus_gcm394_base_device::nand_785b_w %04x\n", machine().describe_context(), data);
1289 	m_nand_785b = data;
1290 }
1291 
nand_785c_w(uint16_t data)1292 void generalplus_gpac800_device::nand_785c_w(uint16_t data)
1293 {
1294 	logerror("%s:sunplus_gcm394_base_device::nand_785c_w %04x\n", machine().describe_context(), data);
1295 	m_nand_785c = data;
1296 }
1297 
nand_785d_w(uint16_t data)1298 void generalplus_gpac800_device::nand_785d_w(uint16_t data)
1299 {
1300 	logerror("%s:sunplus_gcm394_base_device::nand_785d_w %04x\n", machine().describe_context(), data);
1301 	m_nand_785d = data;
1302 }
1303 
1304 // [:maincpu] ':maincpu' (00146D)  jak_tsm
nand_785e_r()1305 uint16_t generalplus_gpac800_device::nand_785e_r()
1306 {
1307 	return 0x0000;
1308 }
1309 
1310 //[:maincpu] ':maincpu' (001490)  jak_tsm
nand_ecc_low_byte_error_flag_1_r()1311 uint16_t generalplus_gpac800_device::nand_ecc_low_byte_error_flag_1_r()
1312 {
1313 	return 0x0000;
1314 }
1315 
1316 /*
1317 UNMAPPED reads  writes
1318 
1319 jak_tsm uses these (all iniitalized near start)
1320 unclear if these are specific to the GPAC800 type, or present in the older types
1321 
1322 [:maincpu] ':maincpu' (00043F):sunplus_gcm394_base_device::unk_w @ 0x780a (data 0x0000)
1323 [:maincpu] ':maincpu' (000442):sunplus_gcm394_base_device::unk_w @ 0x7808 (data 0x0000)
1324 [:maincpu] ':maincpu' (000445):sunplus_gcm394_base_device::unk_w @ 0x782f (data 0x0002)
1325 [:maincpu] ':maincpu' (000449):sunplus_gcm394_base_device::unk_w @ 0x783d (data 0x05d9)
1326 [:maincpu] ':maincpu' (00044D):sunplus_gcm394_base_device::unk_w @ 0x783c (data 0x0a57)
1327 [:maincpu] ':maincpu' (000451):sunplus_gcm394_base_device::unk_w @ 0x783b (data 0x2400)
1328 [:maincpu] ':maincpu' (000454):sunplus_gcm394_base_device::unk_w @ 0x783e (data 0x0002)
1329 [:maincpu] ':maincpu' (000458):sunplus_gcm394_base_device::unk_w @ 0x783a (data 0x3011)
1330 [:maincpu] ':maincpu' (00045B):sunplus_gcm394_base_device::unk_w @ 0x7874 (data 0x0000)
1331 [:maincpu] ':maincpu' (00045D):sunplus_gcm394_base_device::unk_w @ 0x787c (data 0x0000)
1332 [:maincpu] ':maincpu' (00045F):sunplus_gcm394_base_device::unk_w @ 0x7888 (data 0x0000)
1333 [:maincpu] ':maincpu' (000461):sunplus_gcm394_base_device::unk_w @ 0x787e (data 0x0000)
1334 
1335 jak_car2 uses these
1336 
1337 [:maincpu] ':maincpu' (004056):sunplus_gcm394_base_device::unk_w @ 0x782f (data 0x0002)
1338 [:maincpu] ':maincpu' (004059):sunplus_gcm394_base_device::unk_w @ 0x783d (data 0x05d9)
1339 [:maincpu] ':maincpu' (00405C):sunplus_gcm394_base_device::unk_w @ 0x783c (data 0x0a57)
1340 [:maincpu] ':maincpu' (00405F):sunplus_gcm394_base_device::unk_w @ 0x783b (data 0x2400)
1341 [:maincpu] ':maincpu' (004062):sunplus_gcm394_base_device::unk_w @ 0x783e (data 0x0002)
1342 [:maincpu] ':maincpu' (004065):sunplus_gcm394_base_device::unk_w @ 0x783a (data 0x3011)
1343 [:maincpu] ':maincpu' (004069):sunplus_gcm394_base_device::unk_r @ 0x7880
1344 [:maincpu] ':maincpu' (00406F):sunplus_gcm394_base_device::unk_w @ 0x7874 (data 0x1249)
1345 [:maincpu] ':maincpu' (004071):sunplus_gcm394_base_device::unk_w @ 0x787c (data 0x1249)
1346 [:maincpu] ':maincpu' (004073):sunplus_gcm394_base_device::unk_w @ 0x7888 (data 0x1249)
1347 [:maincpu] ':maincpu' (004075):sunplus_gcm394_base_device::unk_w @ 0x787e (data 0x1249)
1348 [:maincpu] ':maincpu' (004088):sunplus_gcm394_base_device::unk_w @ 0x7841 (data 0x000f)
1349 [:maincpu] ':maincpu' (00408F):sunplus_gcm394_base_device::unk_w @ 0x780a (data 0x0000)
1350 [:maincpu] ':maincpu' (004092):sunplus_gcm394_base_device::unk_w @ 0x7808 (data 0x0002)
1351 
1352 [:maincpu] ':maincpu' (03000A):sunplus_gcm394_base_device::unk_w @ 0x7874 (data 0x36db)
1353 [:maincpu] ':maincpu' (03000C):sunplus_gcm394_base_device::unk_w @ 0x787c (data 0x36db)
1354 [:maincpu] ':maincpu' (03000E):sunplus_gcm394_base_device::unk_w @ 0x7888 (data 0x36db)
1355 [:maincpu] ':maincpu' (030010):sunplus_gcm394_base_device::unk_w @ 0x787e (data 0x36db)
1356 [:maincpu] ':maincpu' (030013):sunplus_gcm394_base_device::unk_w @ 0x787f (data 0x0010)
1357 [:maincpu] ':maincpu' (03001D):sunplus_gcm394_base_device::unk_w @ 0x7804 (data 0x1c7f)
1358 [:maincpu] ':maincpu' (030023):sunplus_gcm394_base_device::unk_w @ 0x7805 (data 0xcdf0)
1359 [:maincpu] ':maincpu' (03E645):sunplus_gcm394_base_device::unk_w @ 0x7861 (data 0x1f66)
1360 [:maincpu] ':maincpu' (03E64C):sunplus_gcm394_base_device::unk_w @ 0x786b (data 0x0000)
1361 [:maincpu] ':maincpu' (03E64F):sunplus_gcm394_base_device::unk_w @ 0x7869 (data 0x0000)
1362 [:maincpu] ':maincpu' (03E652):sunplus_gcm394_base_device::unk_w @ 0x786a (data 0x0000)
1363 [:maincpu] ':maincpu' (03E65B):sunplus_gcm394_base_device::unk_w @ 0x7966 (data 0x0001)
1364 [:maincpu] ':maincpu' (03CBD0):sunplus_gcm394_base_device::unk_w @ 0x7871 (data 0x0000)
1365 
1366 -- this one seems like a common alt type of DMA, used in both hw types as it polls 707c status before doing it
1367 [:maincpu] ':maincpu' (03B4C7):sunplus_gcm394_base_device::unk_w @ 0x707c (data 0x0001)
1368 -- also video / alt dma?
1369 [:maincpu] ':maincpu' (068C15):sunplus_gcm394_base_device::unk_r @ 0x707e
1370 
1371 beambox sets things up with different values (ultimately stalls on some check, maybe seeprom?)
1372 
1373 [:maincpu] ':maincpu' (00043F):sunplus_gcm394_base_device::unk_w @ 0x780a (data 0x0000)
1374 [:maincpu] ':maincpu' (000442):sunplus_gcm394_base_device::unk_w @ 0x7808 (data 0x0000)
1375 [:maincpu] ':maincpu' (000445):sunplus_gcm394_base_device::unk_w @ 0x782f (data 0x0002)
1376 [:maincpu] ':maincpu' (000449):sunplus_gcm394_base_device::unk_w @ 0x783d (data 0x05d9)
1377 [:maincpu] ':maincpu' (00044D):sunplus_gcm394_base_device::unk_w @ 0x783c (data 0x0f58)
1378 [:maincpu] ':maincpu' (000451):sunplus_gcm394_base_device::unk_w @ 0x783b (data 0x2400)
1379 [:maincpu] ':maincpu' (000454):sunplus_gcm394_base_device::unk_w @ 0x783e (data 0x0002)
1380 [:maincpu] ':maincpu' (000458):sunplus_gcm394_base_device::unk_w @ 0x783a (data 0x4011)
1381 [:maincpu] ':maincpu' (00045C):sunplus_gcm394_base_device::unk_w @ 0x7874 (data 0x2492)   -- note pair of 4, but different values to above games
1382 [:maincpu] ':maincpu' (00045E):sunplus_gcm394_base_device::unk_w @ 0x787c (data 0x2492)
1383 [:maincpu] ':maincpu' (000460):sunplus_gcm394_base_device::unk_w @ 0x7888 (data 0x2492)
1384 [:maincpu] ':maincpu' (000462):sunplus_gcm394_base_device::unk_w @ 0x787e (data 0x2492)
1385 
1386 vbaby code is very differet, attempts to load NAND block manually, not with DMA
1387 
1388 */
1389 
1390 
1391 // all tilemap registers etc. appear to be in the same place as the above system, including the 'extra' ones not on the earlier models
1392 // so it's likely this is built on top of that just with NAND support
gpac800_internal_map(address_map & map)1393 void generalplus_gpac800_device::gpac800_internal_map(address_map& map)
1394 {
1395 	sunplus_gcm394_base_device::base_internal_map(map);
1396 
1397 	// 785x = NAND device
1398 	map(0x007850, 0x007850).rw(FUNC(generalplus_gpac800_device::nand_7850_status_r), FUNC(generalplus_gpac800_device::nand_7850_w)); // NAND Control Reg
1399 	map(0x007851, 0x007851).w(FUNC(generalplus_gpac800_device::nand_command_w)); // NAND Command Reg
1400 	map(0x007852, 0x007852).w(FUNC(generalplus_gpac800_device::nand_addr_low_w)); // NAND Low Address Reg
1401 	map(0x007853, 0x007853).w(FUNC(generalplus_gpac800_device::nand_addr_high_w)); // NAND High Address Reg
1402 	map(0x007854, 0x007854).r(FUNC(generalplus_gpac800_device::nand_7854_r)); // NAND Data Reg
1403 	map(0x007855, 0x007855).w(FUNC(generalplus_gpac800_device::nand_dma_ctrl_w)); // NAND DMA / INT Control
1404 	map(0x007856, 0x007856).w(FUNC(generalplus_gpac800_device::nand_7856_type_w)); // usually 0x0021?
1405 	map(0x007857, 0x007857).w(FUNC(generalplus_gpac800_device::nand_7857_w));
1406 
1407 	// most of these are likely ECC stuff for testing the ROM?
1408 	map(0x00785b, 0x00785b).w(FUNC(generalplus_gpac800_device::nand_785b_w));
1409 	map(0x00785c, 0x00785c).w(FUNC(generalplus_gpac800_device::nand_785c_w));
1410 	map(0x00785d, 0x00785d).w(FUNC(generalplus_gpac800_device::nand_785d_w));
1411 	map(0x00785e, 0x00785e).r(FUNC(generalplus_gpac800_device::nand_785e_r)); // also ECC status related?
1412 	map(0x00785f, 0x00785f).r(FUNC(generalplus_gpac800_device::nand_ecc_low_byte_error_flag_1_r)); // ECC Low Byte Error Flag 1 (maybe)
1413 
1414 	// 128kwords internal ROM
1415 	//map(0x08000, 0x0ffff).rom().region("internal", 0); // lower 32kwords of internal ROM is visible / shadowed depending on boot pins and register
1416 	map(0x08000, 0x0ffff).r(FUNC(generalplus_gpac800_device::internalrom_lower32_r)).nopw();
1417 	map(0x10000, 0x27fff).rom().region("internal", 0x10000); // upper 96kwords of internal ROM is always visible
1418 	map(0x28000, 0x2ffff).noprw(); // reserved
1419 	// 0x30000+ is CS access
1420 
1421 	map(0x030000, 0x1fffff).rw(FUNC(generalplus_gpac800_device::cs_space_r), FUNC(generalplus_gpac800_device::cs_space_w));
1422 	map(0x200000, 0x3fffff).rw(FUNC(generalplus_gpac800_device::cs_bank_space_r), FUNC(generalplus_gpac800_device::cs_bank_space_w));
1423 }
1424 
1425 
spi_unk_7943_r()1426 uint16_t generalplus_gpspispi_device::spi_unk_7943_r()
1427 {
1428 	return 0x0007;
1429 }
1430 
gpspispi_internal_map(address_map & map)1431 void generalplus_gpspispi_device::gpspispi_internal_map(address_map& map)
1432 {
1433 	sunplus_gcm394_base_device::base_internal_map(map);
1434 
1435 	map(0x007943, 0x007943).r(FUNC(generalplus_gpspispi_device::spi_unk_7943_r));
1436 
1437 	map(0x008000, 0x00ffff).rom().region("internal", 0);
1438 }
1439 
1440 
device_start()1441 void sunplus_gcm394_base_device::device_start()
1442 {
1443 	unsp_20_device::device_start();
1444 
1445 	m_cs_callback.resolve();
1446 
1447 	m_porta_in.resolve_safe(0);
1448 	m_portb_in.resolve_safe(0);
1449 	m_portc_in.resolve_safe(0);
1450 	m_portd_in.resolve_safe(0);
1451 
1452 	m_porta_out.resolve();
1453 	m_portb_out.resolve();
1454 	m_portc_out.resolve();
1455 	m_portd_out.resolve();
1456 
1457 
1458 	m_space_read_cb.resolve_safe(0);
1459 	m_space_write_cb.resolve();
1460 
1461 	m_nand_read_cb.resolve_safe(0);
1462 
1463 	m_unk_timer = timer_alloc(0);
1464 	m_unk_timer->adjust(attotime::never);
1465 
1466 	save_item(NAME(m_dma_params));
1467 	save_item(NAME(m_7803));
1468 	save_item(NAME(m_7807));
1469 	save_item(NAME(m_membankswitch_7810));
1470 	save_item(NAME(m_7816));
1471 	save_item(NAME(m_7817));
1472 	save_item(NAME(m_7819));
1473 	save_item(NAME(m_782x));
1474 	save_item(NAME(m_782d));
1475 	save_item(NAME(m_7835));
1476 	save_item(NAME(m_7860));
1477 	save_item(NAME(m_7861));
1478 	save_item(NAME(m_7862_porta_direction));
1479 	save_item(NAME(m_7863_porta_attribute));
1480 
1481 	save_item(NAME(m_786a_portb_direction));
1482 	save_item(NAME(m_786b_portb_attribute));
1483 
1484 	save_item(NAME(m_7870));
1485 	//save_item(NAME(m_7871));
1486 	save_item(NAME(m_7872_portc_direction));
1487 	save_item(NAME(m_7873_portc_attribute));
1488 	save_item(NAME(m_7882));
1489 	save_item(NAME(m_7883));
1490 	save_item(NAME(m_78a0));
1491 	save_item(NAME(m_78a4));
1492 	save_item(NAME(m_78a5));
1493 	save_item(NAME(m_78a6));
1494 	save_item(NAME(m_78a8));
1495 	save_item(NAME(m_78b0));
1496 	save_item(NAME(m_78b1));
1497 	save_item(NAME(m_78b2));
1498 	save_item(NAME(m_78b8));
1499 	save_item(NAME(m_78f0));
1500 	save_item(NAME(m_78fb));
1501 	save_item(NAME(m_7934));
1502 	save_item(NAME(m_7935));
1503 	save_item(NAME(m_7936));
1504 	save_item(NAME(m_7960));
1505 	save_item(NAME(m_7961));
1506 	save_item(NAME(m_system_dma_memtype));
1507 	save_item(NAME(m_csbase));
1508 	save_item(NAME(m_romtype));
1509 }
1510 
device_reset()1511 void sunplus_gcm394_base_device::device_reset()
1512 {
1513 	unsp_20_device::device_reset();
1514 
1515 	for (int j = 0; j < 3; j++)
1516 	{
1517 		for (int i = 0; i < 7; i++)
1518 		{
1519 			m_dma_params[i][j] = 0x0000;
1520 		}
1521 		m_dma_latched[j] = false;
1522 	}
1523 
1524 	// 78xx unknown
1525 
1526 	m_78fb = 0x0000;
1527 	m_782d = 0x0000;
1528 
1529 	m_7807 = 0x0000;
1530 
1531 	m_membankswitch_7810 = 0x0001;
1532 
1533 	m_7816 = 0x0000;
1534 	m_7817 = 0x0000;
1535 
1536 	m_7819 = 0x0000;
1537 
1538 	m_782x[0] = 0x0000;
1539 	m_782x[1] = 0x0000;
1540 	m_782x[2] = 0x0000;
1541 	m_782x[3] = 0x0000;
1542 	m_782x[4] = 0x0000;
1543 
1544 	m_7835 = 0x0000;
1545 
1546 	m_7860 = 0x0000;
1547 
1548 	m_7861 = 0x0000;
1549 
1550 	m_7862_porta_direction = 0x0000;
1551 	m_7863_porta_attribute = 0x0000;
1552 
1553 	m_786a_portb_direction = 0x0000;
1554 	m_786b_portb_attribute = 0x0000;
1555 
1556 	m_7870 = 0x0000;
1557 
1558 	//m_7871 = 0x0000;
1559 
1560 	m_7872_portc_direction = 0x0000;
1561 	m_7873_portc_attribute = 0x0000;
1562 
1563 	m_7882 = 0x0000;
1564 	m_7883 = 0x0000;
1565 
1566 	m_78a0 = 0x0000;
1567 
1568 	m_78a4 = 0x0000;
1569 	m_78a5 = 0x0000;
1570 	m_78a6 = 0x0000;
1571 
1572 	m_78a8 = 0x0000;
1573 
1574 	m_78b0 = 0x0000;
1575 	m_78b1 = 0x0000;
1576 	m_78b2 = 0x0000;
1577 
1578 	m_78b8 = 0x0000;
1579 	m_78f0 = 0x0000;
1580 
1581 	// 79xx unknown
1582 
1583 	m_7934 = 0x0000;
1584 	m_7935 = 0x0000;
1585 	m_7936 = 0x0000;
1586 
1587 	m_7960 = 0x0000;
1588 	m_7961 = 0x0000;
1589 
1590 	m_system_dma_memtype = 0x0000;
1591 
1592 	m_unk_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
1593 
1594 	m_spg_video->set_video_spaces(this->space(AS_PROGRAM), *m_cs_space, m_csbase);
1595 	m_spg_video->reset();
1596 }
1597 
device_reset()1598 void generalplus_gpac800_device::device_reset()
1599 {
1600 	sunplus_gcm394_base_device::device_reset();
1601 
1602 	m_nand_addr_low = 0x0000;
1603 	m_nand_addr_high = 0x0000;
1604 	m_nand_dma_ctrl = 0x0000;
1605 	m_nand_7850 = 0x0000;
1606 	m_nand_785d = 0x0000;
1607 	m_nand_785c = 0x0000;
1608 	m_nand_785b = 0x0000;
1609 	m_nand_7856 = 0x0000;
1610 	m_nand_7857 = 0x0000;
1611 }
1612 
IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)1613 IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)
1614 {
1615 	//logerror("irq_vector_cb %d\n", irqline);
1616 
1617 	if (irqline == UNSP_IRQ6_LINE)
1618 		set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
1619 
1620 	if (irqline == UNSP_IRQ4_LINE)
1621 		set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
1622 
1623 	return 0;
1624 }
1625 
1626 
checkirq6()1627 void sunplus_gcm394_base_device::checkirq6()
1628 {
1629 /*
1630     if (m_7935 & 0x0100)
1631         set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
1632     else
1633         set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
1634 */
1635 }
1636 
1637 /* the IRQ6 interrupt on Wrlshunt
1638    reads 78a1, checks bit 0400
1639    if it IS set, just increases value in RAM at 1a2e  (no ack)
1640    if it ISN'T set, then read/write 78b2 (ack something?) then increase value in RAM  at 1a2e
1641    (smartfp doesn't touch these addresses? but instead reads/writes 7935, alt ack?)
1642 
1643    wrlshunt also has an IRQ4
1644    it always reads/writes 78c0 before executing payload (ack?)
1645    payload is a lot of manipulation of values in RAM, no registers touched
1646 
1647    wrlshunt also has FIQ
1648    no ack mechanism, for sound timer maybe (as it appears to be on spg110)
1649 
1650 
1651    ----
1652 
1653    IRQ5 is video IRQ
1654    in both games writing 0x0001 to 7063 seems to be an ack mechanism
1655    wrlshunt also checks bit 0x0040 of 7863 and will ack that too with alt code paths
1656 
1657    7863 is therefore some kind of 'video irq source' ?
1658 
1659 */
1660 
1661 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)1662 void sunplus_gcm394_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
1663 {
1664 	switch (id)
1665 	{
1666 	case 0:
1667 	{
1668 		m_7935 |= 0x0100;
1669 		set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
1670 		//set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
1671 
1672 	//  checkirq6();
1673 		break;
1674 	}
1675 	}
1676 }
1677 
1678 
WRITE_LINE_MEMBER(sunplus_gcm394_base_device::audioirq_w)1679 WRITE_LINE_MEMBER(sunplus_gcm394_base_device::audioirq_w)
1680 {
1681 	//set_state_unsynced(UNSP_IRQ5_LINE, state);
1682 }
1683 
WRITE_LINE_MEMBER(sunplus_gcm394_base_device::videoirq_w)1684 WRITE_LINE_MEMBER(sunplus_gcm394_base_device::videoirq_w)
1685 {
1686 	set_state_unsynced(UNSP_IRQ5_LINE, state);
1687 }
1688 
read_space(uint32_t offset)1689 uint16_t sunplus_gcm394_base_device::read_space(uint32_t offset)
1690 {
1691 	address_space& space = this->space(AS_PROGRAM);
1692 	uint16_t val;
1693 	if (offset < m_csbase)
1694 	{
1695 		val = space.read_word(offset);
1696 	}
1697 	else
1698 	{
1699 		val = m_cs_space->read_word(offset-m_csbase);
1700 	}
1701 
1702 	return val;
1703 }
1704 
1705 
1706 
write_space(uint32_t offset,uint16_t data)1707 void sunplus_gcm394_base_device::write_space(uint32_t offset, uint16_t data)
1708 {
1709 	address_space& space = this->space(AS_PROGRAM);
1710 	if (offset < m_csbase)
1711 	{
1712 		space.write_word(offset, data);
1713 	}
1714 	else
1715 	{
1716 		m_cs_space->write_word(offset-m_csbase, data);
1717 	}
1718 }
1719 
1720 
1721 
device_add_mconfig(machine_config & config)1722 void sunplus_gcm394_base_device::device_add_mconfig(machine_config &config)
1723 {
1724 	SUNPLUS_GCM394_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1));
1725 	m_spg_audio->write_irq_callback().set(FUNC(sunplus_gcm394_base_device::audioirq_w));
1726 	m_spg_audio->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
1727 
1728 	m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
1729 	m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
1730 
1731 	GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen);
1732 	m_spg_video->write_video_irq_callback().set(FUNC(sunplus_gcm394_base_device::videoirq_w));
1733 	m_spg_video->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space));
1734 }
1735 
1736 
1737