/*************************************************************************** Cinematronics vector hardware ***************************************************************************/ #include "emu.h" #include "video/vector.h" #include "cpu/ccpu/ccpu.h" #include "includes/cinemat.h" /************************************* * * Constants * *************************************/ enum { COLOR_BILEVEL, COLOR_16LEVEL, COLOR_64LEVEL, COLOR_RGB, COLOR_QB3 }; /************************************* * * Vector rendering * *************************************/ void cinemat_vector_callback(device_t *device, INT16 sx, INT16 sy, INT16 ex, INT16 ey, UINT8 shift) { cinemat_state *state = device->machine().driver_data(); const rectangle &visarea = device->machine().primary_screen->visible_area(); int intensity = 0xff; /* adjust for slop */ sx = sx - visarea.min_x; ex = ex - visarea.min_x; sy = sy - visarea.min_y; ey = ey - visarea.min_y; /* point intensity is determined by the shift value */ if (sx == ex && sy == ey) intensity = 0x1ff * shift / 8; /* move to the starting position if we're not there already */ if (sx != state->m_lastx || sy != state->m_lasty) vector_add_point(device->machine(), sx << 16, sy << 16, 0, 0); /* draw the vector */ vector_add_point(device->machine(), ex << 16, ey << 16, state->m_vector_color, intensity); /* remember the last point */ state->m_lastx = ex; state->m_lasty = ey; } /************************************* * * Vector color handling * *************************************/ WRITE8_HANDLER(cinemat_vector_control_w) { cinemat_state *state = space->machine().driver_data(); int r, g, b, i; cpu_device *cpu = space->machine().device("maincpu"); switch (state->m_color_mode) { case COLOR_BILEVEL: /* color is either bright or dim, selected by the value sent to the port */ state->m_vector_color = (data & 1) ? MAKE_RGB(0x80,0x80,0x80) : MAKE_RGB(0xff,0xff,0xff); break; case COLOR_16LEVEL: /* on the rising edge of the data value, latch bits 0-3 of the */ /* X register as the intensity */ if (data != state->m_last_control && data) { int xval = cpu->state(CCPU_X) & 0x0f; i = (xval + 1) * 255 / 16; state->m_vector_color = MAKE_RGB(i,i,i); } break; case COLOR_64LEVEL: /* on the rising edge of the data value, latch bits 2-7 of the */ /* X register as the intensity */ if (data != state->m_last_control && data) { int xval = cpu->state(CCPU_X); xval = (~xval >> 2) & 0x3f; i = (xval + 1) * 255 / 64; state->m_vector_color = MAKE_RGB(i,i,i); } break; case COLOR_RGB: /* on the rising edge of the data value, latch the X register */ /* as 4-4-4 BGR values */ if (data != state->m_last_control && data) { int xval = cpu->state(CCPU_X); r = (~xval >> 0) & 0x0f; r = r * 255 / 15; g = (~xval >> 4) & 0x0f; g = g * 255 / 15; b = (~xval >> 8) & 0x0f; b = b * 255 / 15; state->m_vector_color = MAKE_RGB(r,g,b); } break; case COLOR_QB3: { /* on the falling edge of the data value, remember the original X,Y values */ /* they will be restored on the rising edge; this is to simulate the fact */ /* that the Rockola color hardware did not overwrite the beam X,Y position */ /* on an IV instruction if data == 0 here */ if (data != state->m_last_control && !data) { state->m_qb3_lastx = cpu->state(CCPU_X); state->m_qb3_lasty = cpu->state(CCPU_Y); } /* on the rising edge of the data value, latch the Y register */ /* as 2-3-3 BGR values */ if (data != state->m_last_control && data) { int yval = cpu->state(CCPU_Y); r = (~yval >> 0) & 0x07; r = r * 255 / 7; g = (~yval >> 3) & 0x07; g = g * 255 / 7; b = (~yval >> 6) & 0x03; b = b * 255 / 3; state->m_vector_color = MAKE_RGB(r,g,b); /* restore the original X,Y values */ cpu->set_state(CCPU_X, state->m_qb3_lastx); cpu->set_state(CCPU_Y, state->m_qb3_lasty); } } break; } /* remember the last value */ state->m_last_control = data; } /************************************* * * Video startup * *************************************/ VIDEO_START( cinemat_bilevel ) { cinemat_state *state = machine.driver_data(); state->m_color_mode = COLOR_BILEVEL; VIDEO_START_CALL(vector); } VIDEO_START( cinemat_16level ) { cinemat_state *state = machine.driver_data(); state->m_color_mode = COLOR_16LEVEL; VIDEO_START_CALL(vector); } VIDEO_START( cinemat_64level ) { cinemat_state *state = machine.driver_data(); state->m_color_mode = COLOR_64LEVEL; VIDEO_START_CALL(vector); } VIDEO_START( cinemat_color ) { cinemat_state *state = machine.driver_data(); state->m_color_mode = COLOR_RGB; VIDEO_START_CALL(vector); } VIDEO_START( cinemat_qb3color ) { cinemat_state *state = machine.driver_data(); state->m_color_mode = COLOR_QB3; VIDEO_START_CALL(vector); } /************************************* * * End-of-frame * *************************************/ SCREEN_UPDATE( cinemat ) { SCREEN_UPDATE_CALL(vector); vector_clear_list(); ccpu_wdt_timer_trigger(screen->machine().device("maincpu")); return 0; } /************************************* * * Space War update * *************************************/ SCREEN_UPDATE( spacewar ) { int sw_option = input_port_read(screen->machine(), "INPUTS"); SCREEN_UPDATE_CALL(cinemat); /* set the state of the artwork */ output_set_value("pressed3", (~sw_option >> 0) & 1); output_set_value("pressed8", (~sw_option >> 1) & 1); output_set_value("pressed4", (~sw_option >> 2) & 1); output_set_value("pressed9", (~sw_option >> 3) & 1); output_set_value("pressed1", (~sw_option >> 4) & 1); output_set_value("pressed6", (~sw_option >> 5) & 1); output_set_value("pressed2", (~sw_option >> 6) & 1); output_set_value("pressed7", (~sw_option >> 7) & 1); output_set_value("pressed5", (~sw_option >> 10) & 1); output_set_value("pressed0", (~sw_option >> 11) & 1); return 0; }