1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol, Robbbert
3 
4 #include "emu.h"
5 #include "includes/gamecom.h"
6 
7 #include "screen.h"
8 
9 
10 static const int gamecom_timer_limit[8] = { 2, 1024, 2048, 4096, 8192, 16384, 32768, 65536 };
11 
TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_clock_timer_callback)12 TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_clock_timer_callback)
13 {
14 	uint8_t val = m_p_ram[SM8521_CLKT] + 1;
15 	m_p_ram[SM8521_CLKT] = ( m_p_ram[SM8521_CLKT] & 0xC0 ) | (val & 0x3f);
16 	m_maincpu->set_input_line(sm8500_cpu_device::CK_INT, ASSERT_LINE );
17 }
18 
TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_sound0_timer_callback)19 TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_sound0_timer_callback)
20 {
21 	if (m_sound0_cnt > 0x3f)
22 	{
23 		if (m_sound.sg0t > 0)
24 		{
25 			m_sound0_timer->adjust(attotime::from_hz(2764800/m_sound.sg0t), 0, attotime::from_hz(2764800/m_sound.sg0t));
26 			if ((m_sound.sgc & 0x81) == 0x81)
27 				m_sound0_cnt = 0;
28 		}
29 	}
30 	if (m_sound0_cnt < 0x40)
31 	{
32 		m_dac0->write((m_sound.sg0w[m_sound0_cnt >> 1] >> (BIT(m_sound0_cnt, 0) * 4)) & 0xf);
33 		m_sound0_cnt++;
34 	}
35 }
36 
TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_sound1_timer_callback)37 TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_sound1_timer_callback)
38 {
39 	if (m_sound1_cnt > 0x3f)
40 	{
41 		if (m_sound.sg1t > 0)
42 		{
43 			m_sound1_timer->adjust(attotime::from_hz(2764800/m_sound.sg1t), 0, attotime::from_hz(2764800/m_sound.sg1t));
44 			if ((m_sound.sgc & 0x82) == 0x82)
45 				m_sound1_cnt = 0;
46 		}
47 	}
48 	if (m_sound1_cnt < 0x40)
49 	{
50 		m_dac1->write((m_sound.sg1w[m_sound1_cnt >> 1] >> (BIT(m_sound1_cnt, 0) * 4)) & 0xf);
51 		m_sound1_cnt++;
52 	}
53 }
54 
machine_reset()55 void gamecom_state::machine_reset()
56 {
57 	uint8_t *rom = m_region_kernel->base();
58 	m_bank1->set_base(rom);
59 	m_bank2->set_base(rom);
60 	m_bank3->set_base(rom);
61 	m_bank4->set_base(rom);
62 
63 	m_cart_ptr = nullptr;
64 	m_lch_reg = 0x07;
65 	m_lcv_reg = 0x27;
66 	m_lcdc_reg = 0xb0;
67 	m_sound0_cnt = 0x40;
68 	m_sound1_cnt = 0x40;
69 
70 	std::string region_tag;
71 	m_cart1_rom = memregion(region_tag.assign(m_cart1->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
72 	m_cart2_rom = memregion(region_tag.assign(m_cart2->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
73 }
74 
gamecom_set_mmu(uint8_t mmu,uint8_t data)75 void gamecom_state::gamecom_set_mmu(uint8_t mmu, uint8_t data)
76 {
77 	if (data < 0x20)
78 	{
79 		/* select internal ROM bank */
80 		switch (mmu)
81 		{
82 			case 1: m_bank1->set_base(m_region_kernel->base() + (data << 13)); break;
83 			case 2: m_bank2->set_base(m_region_kernel->base() + (data << 13)); break;
84 			case 3: m_bank3->set_base(m_region_kernel->base() + (data << 13)); break;
85 			case 4: m_bank4->set_base(m_region_kernel->base() + (data << 13)); break;
86 		}
87 	}
88 	else
89 	{
90 		/* select cartridge bank */
91 		if (m_cart_ptr)
92 		{
93 			switch (mmu)
94 			{
95 				case 1: m_bank1->set_base(m_cart_ptr + (data << 13)); break;
96 				case 2: m_bank2->set_base(m_cart_ptr + (data << 13)); break;
97 				case 3: m_bank3->set_base(m_cart_ptr + (data << 13)); break;
98 				case 4: m_bank4->set_base(m_cart_ptr + (data << 13)); break;
99 			}
100 		}
101 	}
102 }
103 
handle_stylus_press(int column)104 void gamecom_state::handle_stylus_press( int column )
105 {
106 	uint16_t data = m_io_grid[column]->read();
107 	if (data)
108 	{
109 		uint16_t stylus_y = data ^ 0x3ff;
110 		m_p_ram[SM8521_P0] = stylus_y;
111 		m_p_ram[SM8521_P1] = ( m_p_ram[SM8521_P1] & 0xFC ) | ( stylus_y >> 8 );
112 	}
113 	else
114 	{
115 		m_p_ram[SM8521_P0] = 0xFF;
116 		m_p_ram[SM8521_P1] |= 3;
117 	}
118 }
119 
handle_input_press(uint16_t mux_data)120 void gamecom_state::handle_input_press(uint16_t mux_data)
121 {
122 	switch( mux_data )
123 	{
124 		case 0xFFFB:
125 			/* column #0 */
126 			/* P0 bit 0 cleared => 01 */
127 			/* P0 bit 1 cleared => 0E */
128 			/* P0 bit 2 cleared => 1B */
129 			/* P0 bit 3 cleared => etc */
130 			/* P0 bit 4 cleared => */
131 			/* P0 bit 5 cleared => */
132 			/* P0 bit 6 cleared => */
133 			/* P0 bit 7 cleared => */
134 			/* P1 bit 0 cleared => */
135 			/* P1 bit 1 cleared => */
136 			handle_stylus_press(0);
137 			break;
138 		case 0xFFF7:    /* column #1 */
139 			handle_stylus_press(1);
140 			break;
141 		case 0xFFEF:    /* column #2 */
142 			handle_stylus_press(2);
143 			break;
144 		case 0xFFDF:    /* column #3 */
145 			handle_stylus_press(3);
146 			break;
147 		case 0xFFBF:    /* column #4 */
148 			handle_stylus_press(4);
149 			break;
150 		case 0xFF7F:    /* column #5 */
151 			handle_stylus_press(5);
152 			break;
153 		case 0xFEFF:    /* column #6 */
154 			handle_stylus_press(6);
155 			break;
156 		case 0xFDFF:    /* column #7 */
157 			handle_stylus_press(7);
158 			break;
159 		case 0xFBFF:    /* column #8 */
160 			handle_stylus_press(8);
161 			break;
162 		case 0xF7FF:    /* column #9 */
163 			handle_stylus_press(9);
164 			break;
165 		case 0xEFFF:    /* column #10 */
166 			handle_stylus_press(10);
167 			break;
168 		case 0xDFFF:    /* column #11 */
169 			handle_stylus_press(11);
170 			break;
171 		case 0xBFFF:    /* column #12 */
172 			handle_stylus_press(12);
173 			break;
174 		case 0x7FFF:    /* keys #1 */
175 			/* P0 bit 0 cleared => 83 (up) */
176 			/* P0 bit 1 cleared => 84 (down) */
177 			/* P0 bit 2 cleared => 85 (left) */
178 			/* P0 bit 3 cleared => 86 (right) */
179 			/* P0 bit 4 cleared => 87 (menu) */
180 			/* P0 bit 5 cleared => 8A (pause) */
181 			/* P0 bit 6 cleared => 89 (sound) */
182 			/* P0 bit 7 cleared => 8B (button A) */
183 			/* P1 bit 0 cleared => 8C (button B) */
184 			/* P1 bit 1 cleared => 8D (button C) */
185 			m_p_ram[SM8521_P0] = m_io_in0->read();
186 			m_p_ram[SM8521_P1] = (m_p_ram[SM8521_P1] & 0xFC) | ( m_io_in1->read() & 3 );
187 			break;
188 		case 0xFFFF:    /* keys #2 */
189 			/* P0 bit 0 cleared => 88 (power) */
190 			/* P0 bit 1 cleared => 8E (button D) */
191 			/* P0 bit 2 cleared => A0 */
192 			/* P0 bit 3 cleared => A0 */
193 			/* P0 bit 4 cleared => A0 */
194 			/* P0 bit 5 cleared => A0 */
195 			/* P0 bit 6 cleared => A0 */
196 			/* P0 bit 7 cleared => A0 */
197 			/* P1 bit 0 cleared => A0 */
198 			/* P1 bit 1 cleared => A0 */
199 			m_p_ram[SM8521_P0] = (m_p_ram[SM8521_P0] & 0xFC) | ( m_io_in2->read() & 3 );
200 			m_p_ram[SM8521_P1] = 0xFF;
201 			break;
202 	}
203 }
204 
gamecom_pio_w(offs_t offset,uint8_t data)205 void gamecom_state::gamecom_pio_w(offs_t offset, uint8_t data)
206 {
207 	offset += 0x14;
208 	m_p_ram[offset] = data;
209 	switch (offset)
210 	{
211 		case SM8521_P1:
212 		case SM8521_P2:
213 			handle_input_press(m_p_ram[SM8521_P1] | (m_p_ram[SM8521_P2] << 8));
214 			break;
215 		case SM8521_P3:
216 				/* P3 bit7 clear, bit6 set -> enable cartridge port #0? */
217 				/* P3 bit6 clear, bit7 set -> enable cartridge port #1? */
218 				switch (data & 0xc0)
219 				{
220 				case 0x40: m_cart_ptr = m_cart1_rom != nullptr ? m_cart1_rom->base() : nullptr; break;
221 				case 0x80: m_cart_ptr = m_cart2_rom != nullptr ? m_cart2_rom->base() : nullptr; break;
222 				default:   m_cart_ptr = nullptr;       break;
223 				}
224 				return;
225 	}
226 }
227 
gamecom_pio_r(offs_t offset)228 uint8_t gamecom_state::gamecom_pio_r(offs_t offset)
229 {
230 	return m_p_ram[offset + 0x14];
231 }
232 
gamecom_internal_r(offs_t offset)233 uint8_t gamecom_state::gamecom_internal_r(offs_t offset)
234 {
235 	return m_p_ram[offset + 0x20];
236 }
237 
238 /* TODO: preliminary, proper formula not yet understood (and manual doesn't help much either) */
recompute_lcd_params()239 void gamecom_state::recompute_lcd_params()
240 {
241 	int vblank_period,hblank_period;
242 	int H_timing,V_timing;
243 	int pixel_clock;
244 	attoseconds_t refresh;
245 
246 	if(m_lch_reg != 7)
247 		popmessage("LCH = %02x!",m_lch_reg);
248 
249 	if((m_lcdc_reg & 0xf) != 0)
250 		popmessage("LCDC = %02x!",m_lcdc_reg);
251 
252 	if(m_lcv_reg != 0x27)
253 		popmessage("LCV = %02x!",m_lcv_reg);
254 
255 	H_timing = ((m_lch_reg & 0x1f) + 1) * 200/4;
256 	V_timing = (m_lcv_reg & 0x1f);
257 	pixel_clock = (XTAL(11'059'200) / 2).value(); // TODO: divisor actually settable
258 
259 	rectangle visarea(0, 200-1, 0, 160-1); // TODO: check settings
260 
261 	vblank_period = (V_timing + 160);
262 	hblank_period = (H_timing + 200);
263 
264 	refresh  = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period;
265 	m_screen->configure(hblank_period, vblank_period, visarea, refresh);
266 }
267 
gamecom_internal_w(offs_t offset,uint8_t data)268 void gamecom_state::gamecom_internal_w(offs_t offset, uint8_t data)
269 {
270 	offset += 0x20;
271 	switch( offset )
272 	{
273 	case SM8521_MMU0:   /* disable bootstrap ROM? most likely not written to on game.com */
274 		logerror( "Write to MMU0\n" );
275 		break;
276 	case SM8521_MMU1:
277 		gamecom_set_mmu(1, data);
278 		break;
279 	case SM8521_MMU2:
280 		gamecom_set_mmu(2, data);
281 		break;
282 	case SM8521_MMU3:
283 		gamecom_set_mmu(3, data);
284 		break;
285 	case SM8521_MMU4:
286 		gamecom_set_mmu(4, data);
287 		break;
288 
289 	/* Video hardware and DMA */
290 	case SM8521_DMBR:
291 		data &= 0x7f;
292 		break;
293 	case SM8521_TM0D:
294 		m_timer[0].upcounter_max = data;
295 		data = 0;
296 		break;
297 	case SM8521_TM0C:
298 		m_timer[0].enabled = BIT(data, 7);
299 		m_timer[0].prescale_max = gamecom_timer_limit[data & 0x07] >> 1;
300 		m_timer[0].prescale_count = 0;
301 		m_p_ram[SM8521_TM0D] = 0;
302 		break;
303 	case SM8521_TM1D:
304 		m_timer[1].upcounter_max = data;
305 		data = 0;
306 		break;
307 	case SM8521_TM1C:
308 		m_timer[1].enabled = BIT(data, 7);
309 		m_timer[1].prescale_max = gamecom_timer_limit[data & 0x07] >> 1;
310 		m_timer[1].prescale_count = 0;
311 		m_p_ram[SM8521_TM1D] = 0;
312 		break;
313 	case SM8521_CLKT:   /* bit 6-7 */
314 		if ( data & 0x80 )
315 		{
316 			/* timer run */
317 			if ( data & 0x40 )
318 			{
319 				/* timer resolution 1 minute */
320 				m_clock_timer->adjust(attotime::from_seconds(60), 0, attotime::from_seconds(60));
321 			}
322 			else
323 			{
324 				/* TImer resolution 1 second */
325 				m_clock_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
326 			}
327 		}
328 		else
329 		{
330 			/* disable timer reset */
331 			m_clock_timer->enable( 0 );
332 			data &= 0xC0;
333 		}
334 		break;
335 
336 	case SM8521_LCDC:
337 		m_lcdc_reg = data;
338 		recompute_lcd_params();
339 		break;
340 
341 	case SM8521_LCH:
342 		/*
343 		--x- ---- Horizontal DOT size (160 / 200)
344 		---x xxxx H-Timing bits
345 		*/
346 		m_lch_reg = data;
347 		recompute_lcd_params();
348 		break;
349 
350 	case SM8521_LCV:
351 		/*
352 		x--- ---- V-blank bit (R)
353 		-xx- ---- V-line size bits (100 / 160 / 200 / undef)
354 		---x xxxx V-Blank width bits
355 		*/
356 		m_lcv_reg = data;
357 		recompute_lcd_params();
358 		break;
359 
360 	/* Sound */
361 	case SM8521_SGC:
362 		/*
363 		x--- ---- enable sound output
364 		---- x--- enable DAC
365 		---- -x-- enable SG2
366 		---- --x- enable SG1
367 		---- ---x enable SG0
368 		*/
369 		m_sound.sgc = data;
370 		break;
371 	case SM8521_SG0L:
372 		m_sound.sg0l = data;
373 		break;
374 	case SM8521_SG1L:
375 		m_sound.sg1l = data;
376 		break;
377 	case SM8521_SG0TH:
378 		m_sound.sg0t = ( m_sound.sg0t & 0xFF ) | ( data << 8 );
379 		break;
380 	case SM8521_SG0TL:
381 		m_sound.sg0t = ( m_sound.sg0t & 0xFF00 ) | data;
382 		break;
383 	case SM8521_SG1TH:
384 		m_sound.sg1t = ( m_sound.sg1t & 0xFF ) | ( data << 8 );
385 		break;
386 	case SM8521_SG1TL:
387 		m_sound.sg1t = ( m_sound.sg1t & 0xFF00 ) | data;
388 		break;
389 	case SM8521_SG2L:
390 		m_sound.sg2l = data;
391 		break;
392 	case SM8521_SG2TH:
393 		m_sound.sg2t = ( m_sound.sg2t & 0xFF ) | ( data << 8 );
394 		break;
395 	case SM8521_SG2TL:
396 		m_sound.sg2t = ( m_sound.sg2t & 0xFF00 ) | data;
397 		break;
398 	case SM8521_SGDA:
399 		m_sound.sgda = data;
400 		if((m_sound.sgc & 0x8f) == 0x88)
401 			m_dac->write(data);
402 		break;
403 
404 	case SM8521_SG0W0:
405 	case SM8521_SG0W1:
406 	case SM8521_SG0W2:
407 	case SM8521_SG0W3:
408 	case SM8521_SG0W4:
409 	case SM8521_SG0W5:
410 	case SM8521_SG0W6:
411 	case SM8521_SG0W7:
412 	case SM8521_SG0W8:
413 	case SM8521_SG0W9:
414 	case SM8521_SG0W10:
415 	case SM8521_SG0W11:
416 	case SM8521_SG0W12:
417 	case SM8521_SG0W13:
418 	case SM8521_SG0W14:
419 	case SM8521_SG0W15:
420 		m_sound.sg0w[offset - SM8521_SG0W0] = data;
421 		break;
422 	case SM8521_SG1W0:
423 	case SM8521_SG1W1:
424 	case SM8521_SG1W2:
425 	case SM8521_SG1W3:
426 	case SM8521_SG1W4:
427 	case SM8521_SG1W5:
428 	case SM8521_SG1W6:
429 	case SM8521_SG1W7:
430 	case SM8521_SG1W8:
431 	case SM8521_SG1W9:
432 	case SM8521_SG1W10:
433 	case SM8521_SG1W11:
434 	case SM8521_SG1W12:
435 	case SM8521_SG1W13:
436 	case SM8521_SG1W14:
437 	case SM8521_SG1W15:
438 		m_sound.sg1w[offset - SM8521_SG1W0] = data;
439 		break;
440 
441 	/* Reserved addresses */
442 	case SM8521_18: case SM8521_1B:
443 	case SM8521_29: case SM8521_2A: case SM8521_2F:
444 	case SM8521_33: case SM8521_3E: case SM8521_3F:
445 	case SM8521_41: case SM8521_43: case SM8521_45: case SM8521_4B:
446 	case SM8521_4F:
447 	case SM8521_55: case SM8521_56: case SM8521_57: case SM8521_58:
448 	case SM8521_59: case SM8521_5A: case SM8521_5B: case SM8521_5C:
449 	case SM8521_5D:
450 		logerror( "%X: Write to reserved address (0x%02X). Value written: 0x%02X\n", m_maincpu->pc(), offset, data );
451 		break;
452 	}
453 	m_p_ram[offset] = data;
454 }
455 
456 
457 /* The manual is not conclusive as to which bit of the DMVP register (offset 0x3D) determines
458    which page for source or destination is used.
459    Also, there's nothing about what happens if the block overflows the source or destination. */
gamecom_handle_dma(uint8_t data)460 void gamecom_state::gamecom_handle_dma(uint8_t data)
461 {
462 	u8 dmc = m_p_ram[SM8521_DMC];
463 	if (!BIT(dmc, 7))
464 		return;
465 
466 	m_dma.overwrite_mode = BIT(dmc, 0);
467 	m_dma.transfer_mode = dmc & 0x06;
468 	m_dma.adjust_x = BIT(dmc, 3) ? -1 : 1;
469 	m_dma.decrement_y = BIT(dmc, 4);
470 
471 	m_dma.block_width = m_p_ram[SM8521_DMDX];
472 	m_dma.block_height = m_p_ram[SM8521_DMDY];
473 	m_dma.source_x = m_p_ram[SM8521_DMX1];
474 	m_dma.source_x_current = m_dma.source_x & 3;
475 	m_dma.source_y = m_p_ram[SM8521_DMY1];
476 	m_dma.source_width = ( m_p_ram[SM8521_LCH] & 0x20 ) ? 50 : 40;
477 	m_dma.dest_width = m_dma.source_width;
478 	m_dma.dest_x = m_p_ram[SM8521_DMX2];
479 	m_dma.dest_x_current = m_dma.dest_x & 3;
480 	m_dma.dest_y = m_p_ram[SM8521_DMY2];
481 	m_dma.palette = m_p_ram[SM8521_DMPL];
482 	m_dma.source_mask = 0x1FFF;
483 	m_dma.dest_mask = 0x1FFF;
484 	m_dma.source_bank = &m_p_videoram[BIT(m_p_ram[SM8521_DMVP], 0) ? 0x2000 : 0x0000];
485 	m_dma.dest_bank   = &m_p_videoram[BIT(m_p_ram[SM8521_DMVP], 1) ? 0x2000 : 0x0000];
486 //  logerror("DMA: width %Xx%X, source (%X,%X), dest (%X,%X), transfer_mode %X, banks %X \n", block_width, block_height, m_dma.source_x, m_dma.source_y, m_dma.dest_x, m_dma.dest_y, transfer_mode, m_p_ram[SM8521_DMVP] );
487 //  logerror( "   Palette: %d, %d, %d, %d\n", m_dma.palette[0], m_dma.palette[1], m_dma.palette[2], m_dma.palette[3] );
488 	switch( m_dma.transfer_mode )
489 	{
490 	case 0x00:
491 		/* VRAM->VRAM */
492 		break;
493 	case 0x02:
494 		/* ROM->VRAM */
495 //      logerror( "DMA DMBR = %X\n", m_p_ram[SM8521_DMBR] );
496 		m_dma.source_width = 64;
497 		m_dma.source_mask = 0x3FFF;
498 		if (m_p_ram[SM8521_DMBR] < 16)
499 			m_dma.source_bank = m_region_kernel->base() + (m_p_ram[SM8521_DMBR] << 14);
500 		else
501 		if (m_cart_ptr)
502 			m_dma.source_bank = m_cart_ptr + (m_p_ram[SM8521_DMBR] << 14);
503 		break;
504 	case 0x04:
505 		/* Extend RAM->VRAM */
506 		m_dma.source_width = 64;
507 		m_dma.source_bank = &m_p_nvram[0x0000];
508 		break;
509 	case 0x06:
510 		/* VRAM->Extend RAM */
511 		m_dma.dest_width = 64;
512 		m_dma.dest_bank = &m_p_nvram[0x0000];
513 		break;
514 	}
515 	m_dma.source_current = m_dma.source_width * m_dma.source_y;
516 	m_dma.source_current += m_dma.source_x >> 2;
517 	m_dma.dest_current = m_dma.dest_width * m_dma.dest_y;
518 	m_dma.dest_current += m_dma.dest_x >> 2;
519 	m_dma.source_line = m_dma.source_current;
520 	m_dma.dest_line = m_dma.dest_current;
521 
522 	for( u16 y_count = 0; y_count <= m_dma.block_height; y_count++ )
523 	{
524 		for( u16 x_count = 0; x_count <= m_dma.block_width; x_count++ )
525 		{
526 			u16 src_addr = m_dma.source_current & m_dma.source_mask;
527 			u16 dst_addr = m_dma.dest_current & m_dma.dest_mask;
528 			u8 dst_adj = (m_dma.dest_x_current ^ 3) << 1;
529 			u8 src_adj = (m_dma.source_x_current ^ 3) << 1;
530 
531 			/* handle DMA for 1 pixel */
532 			// Get new pixel
533 			u8 source_pixel = (m_dma.source_bank[src_addr] >> src_adj) & 3;
534 
535 			// If overwrite mode, write new pixel
536 			if ( m_dma.overwrite_mode || source_pixel)
537 			{
538 				// Get 4 pixels and remove the one about to be replaced
539 				u8 other_pixels = m_dma.dest_bank[dst_addr] & ~(3 << dst_adj);
540 				// Get palette of new pixel and place into the hole
541 				m_dma.dest_bank[dst_addr] = other_pixels | (((m_dma.palette >> (source_pixel << 1)) & 3) << dst_adj);
542 			}
543 
544 			/* Advance a pixel */
545 			m_dma.source_x_current += m_dma.adjust_x;
546 			if (BIT(m_dma.source_x_current, 2))
547 			{
548 				m_dma.source_current += m_dma.adjust_x;
549 				m_dma.source_x_current &= 3;
550 			}
551 
552 			m_dma.dest_x_current++;
553 			if (BIT(m_dma.dest_x_current, 2))
554 			{
555 				m_dma.dest_current++;
556 				m_dma.dest_x_current &= 3;
557 			}
558 		}
559 
560 		/* Advance a line */
561 		m_dma.source_x_current = m_dma.source_x & 3;
562 		m_dma.dest_x_current = m_dma.dest_x & 3;
563 		if ( m_dma.decrement_y )
564 			m_dma.source_line -= m_dma.source_width;
565 		else
566 			m_dma.source_line += m_dma.source_width;
567 		m_dma.source_current = m_dma.source_line;
568 		m_dma.dest_line += m_dma.dest_width;
569 		m_dma.dest_current = m_dma.dest_line;
570 	}
571 
572 	m_p_ram[SM8521_DMC] &= 0x7f;  // finished; turn off dma
573 	m_maincpu->set_input_line(sm8500_cpu_device::DMA_INT, ASSERT_LINE );
574 }
575 
gamecom_update_timers(uint8_t data)576 void gamecom_state::gamecom_update_timers(uint8_t data)
577 {
578 	if ( m_timer[0].enabled )
579 	{
580 		m_timer[0].prescale_count += data;
581 		while ( m_timer[0].prescale_count >= m_timer[0].prescale_max )
582 		{
583 			m_timer[0].prescale_count -= m_timer[0].prescale_max;
584 			m_p_ram[SM8521_TM0D]++;
585 			if ( m_p_ram[SM8521_TM0D] >= m_timer[0].upcounter_max )
586 			{
587 				m_p_ram[SM8521_TM0D] = 0;
588 				// check if irq is enabled before calling,
589 				// to stop monopoly choking up the interrupt queue
590 				if (BIT(m_p_ram[SM8521_IE0], 6) && BIT(m_p_ram[SM8521_PS1], 0))
591 					m_maincpu->set_input_line(sm8500_cpu_device::TIM0_INT, ASSERT_LINE );
592 			}
593 		}
594 	}
595 	if ( m_timer[1].enabled )
596 	{
597 		m_timer[1].prescale_count += data;
598 		while ( m_timer[1].prescale_count >= m_timer[1].prescale_max )
599 		{
600 			m_timer[1].prescale_count -= m_timer[1].prescale_max;
601 			m_p_ram[SM8521_TM1D]++;
602 			if ( m_p_ram[SM8521_TM1D] >= m_timer[1].upcounter_max )
603 			{
604 				m_p_ram[SM8521_TM1D] = 0;
605 				if (BIT(m_p_ram[SM8521_IE1], 6) && BIT(m_p_ram[SM8521_PS1], 0) && ((m_p_ram[SM8521_PS0] & 7) < 4))
606 					m_maincpu->set_input_line(sm8500_cpu_device::TIM1_INT, ASSERT_LINE );
607 			}
608 		}
609 	}
610 }
611 
init_gamecom()612 void gamecom_state::init_gamecom()
613 {
614 	m_clock_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gamecom_state::gamecom_clock_timer_callback),this));
615 	m_sound0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gamecom_state::gamecom_sound0_timer_callback),this));
616 	m_sound1_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gamecom_state::gamecom_sound1_timer_callback),this));
617 	m_sound0_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
618 	m_sound1_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
619 	m_p_ram = m_region_maincpu->base(); // required here because pio_w gets called before machine_reset
620 }
621 
common_load(device_image_interface & image,generic_slot_device * slot)622 image_init_result gamecom_state::common_load(device_image_interface &image, generic_slot_device *slot)
623 {
624 	uint32_t size = slot->common_get_size("rom");
625 	uint32_t load_offset = 0;
626 
627 	if (size != 0x008000 && size != 0x040000 && size != 0x080000
628 			&& size != 0x100000 && size != 0x1c0000 && size != 0x200000)
629 	{
630 		image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
631 		return image_init_result::FAIL;
632 	}
633 
634 	if (size == 0x1c0000)
635 		load_offset = 0x40000;
636 
637 	// in order to simplify banked access from the driver, we always allocate 0x200000,
638 	slot->rom_alloc(0x200000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
639 	// we load what we have
640 	slot->common_load_rom(slot->get_rom_base() + load_offset, size, "rom");
641 	// and then we mirror the content, instead of masking out larger accesses
642 	uint8_t *crt = slot->get_rom_base();
643 	if (size < 0x010000) { memcpy(crt + 0x008000, crt, 0x008000); } /* ->64KB */
644 	if (size < 0x020000) { memcpy(crt + 0x010000, crt, 0x010000); } /* ->128KB */
645 	if (size < 0x040000) { memcpy(crt + 0x020000, crt, 0x020000); } /* ->256KB */
646 	if (size < 0x080000) { memcpy(crt + 0x040000, crt, 0x040000); } /* ->512KB */
647 	if (size < 0x100000) { memcpy(crt + 0x080000, crt, 0x080000); } /* ->1MB */
648 	if (size < 0x1c0000) { memcpy(crt + 0x100000, crt, 0x100000); } /* -> >=1.8MB */
649 
650 	return image_init_result::PASS;
651 }
652 
DEVICE_IMAGE_LOAD_MEMBER(gamecom_state::cart1_load)653 DEVICE_IMAGE_LOAD_MEMBER( gamecom_state::cart1_load )
654 {
655 	return common_load(image, m_cart1);
656 }
657 
DEVICE_IMAGE_LOAD_MEMBER(gamecom_state::cart2_load)658 DEVICE_IMAGE_LOAD_MEMBER( gamecom_state::cart2_load )
659 {
660 	return common_load(image, m_cart2);
661 }
662