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