trunk/src/mame/drivers/imolagp.c
| r20326 | r20327 | |
| 5 | 5 | TODO: |
| 6 | 6 | - document remaining dips |
| 7 | 7 | - need better mappings for shifter, currently 3 buttons |
| 8 | | - improve analog steering |
| 9 | | - correct timing (cpu and video) - see sprites disappear partially |
| 10 | | - vreg[0xf] autosteering |
| 8 | - cpu/audio clocks, the XTAL on pcb is unlabeled |
| 9 | - correct video timing, see sprites disappear partially |
| 10 | - vreg[0xf] autosteering, the car should probably only auto-steer when |
| 11 | it gets on the grass(road edges) at high speed. How does the hardware |
| 12 | know the sprite position then? |
| 11 | 13 | - verify colors |
| 12 | 14 | |
| 13 | 15 | ======================================== |
| r20326 | r20327 | |
| 89 | 91 | imolagp_state(const machine_config &mconfig, device_type type, const char *tag) |
| 90 | 92 | : driver_device(mconfig, type, tag), |
| 91 | 93 | m_maincpu(*this, "maincpu"), |
| 92 | | m_slavecpu(*this, "slave") |
| 94 | m_slavecpu(*this, "slave"), |
| 95 | m_steer_pot_timer(*this, "pot"), |
| 96 | m_steer_inp(*this, "STEER") |
| 93 | 97 | { } |
| 94 | 98 | |
| 95 | 99 | required_device<cpu_device> m_maincpu; |
| 96 | 100 | required_device<cpu_device> m_slavecpu; |
| 101 | required_device<timer_device> m_steer_pot_timer; |
| 102 | required_ioport m_steer_inp; |
| 97 | 103 | |
| 98 | 104 | UINT8 m_videoram[2][0x4000]; // 2 layers of 16KB |
| 99 | 105 | UINT8 m_comms_latch[2]; |
| r20326 | r20327 | |
| 102 | 108 | UINT8 m_scroll; |
| 103 | 109 | UINT8 m_steerlatch; |
| 104 | 110 | UINT8 m_draw_mode; |
| 105 | | UINT8 m_oldsteer; |
| 106 | 111 | |
| 107 | 112 | DECLARE_WRITE8_MEMBER(transmit_data_w); |
| 108 | 113 | DECLARE_READ8_MEMBER(trigger_slave_nmi_r); |
| r20326 | r20327 | |
| 115 | 120 | DECLARE_WRITE8_MEMBER(vreg_data_w); |
| 116 | 121 | DECLARE_CUSTOM_INPUT_MEMBER(imolagp_steerlatch_r); |
| 117 | 122 | INTERRUPT_GEN_MEMBER(slave_vblank_irq); |
| 123 | TIMER_DEVICE_CALLBACK_MEMBER(imolagp_pot_callback); |
| 118 | 124 | |
| 119 | 125 | virtual void machine_start(); |
| 120 | 126 | virtual void machine_reset(); |
| r20326 | r20327 | |
| 133 | 139 | void imolagp_state::palette_init() |
| 134 | 140 | { |
| 135 | 141 | // palette seems like 3bpp + intensity |
| 142 | // this still needs to be verified |
| 136 | 143 | for (int i = 0; i < 8; i++) |
| 137 | 144 | { |
| 138 | 145 | palette_set_color_rgb(machine(), i*4+0, 0, 0, 0); |
| r20326 | r20327 | |
| 184 | 191 | |
| 185 | 192 | /*************************************************************************** |
| 186 | 193 | |
| 194 | Interrupts |
| 195 | |
| 196 | ***************************************************************************/ |
| 197 | |
| 198 | TIMER_DEVICE_CALLBACK_MEMBER(imolagp_state::imolagp_pot_callback) |
| 199 | { |
| 200 | int steer = m_steer_inp->read(); |
| 201 | if (steer & 0x7f) |
| 202 | { |
| 203 | if (~steer & 0x80) |
| 204 | { |
| 205 | // shift register when steering left |
| 206 | steer = -steer; |
| 207 | m_steerlatch = (m_steerlatch << 1) | (~m_steerlatch >> 1 & 1); |
| 208 | } |
| 209 | |
| 210 | // steering speed is determined by timer period |
| 211 | // these values(in usec) may need tweaking: |
| 212 | const int base = 6500; |
| 213 | const int range = 100000; |
| 214 | m_steer_pot_timer->adjust(attotime::from_usec(base + range * (1.0 / (double)(steer & 0x7f)))); |
| 215 | m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 216 | } |
| 217 | else |
| 218 | m_steer_pot_timer->adjust(attotime::from_msec(20)); |
| 219 | } |
| 220 | |
| 221 | INTERRUPT_GEN_MEMBER(imolagp_state::slave_vblank_irq) |
| 222 | { |
| 223 | m_scroll = m_vreg[0xe]; // latch scroll |
| 224 | device.execute().set_input_line(0, HOLD_LINE); |
| 225 | } |
| 226 | |
| 227 | |
| 228 | |
| 229 | /*************************************************************************** |
| 230 | |
| 187 | 231 | I/O and Memory Maps |
| 188 | 232 | |
| 189 | 233 | ***************************************************************************/ |
| 190 | 234 | |
| 191 | 235 | /* The master CPU transmits data to the slave CPU one word at a time using a rapid sequence of triggered NMIs. |
| 192 | | * The slave CPU pauses as it enters its irq, awaiting this burst of data. |
| 236 | * The slave CPU pauses as it enters its vblank irq, awaiting this burst of data. |
| 193 | 237 | * Handling the NMI takes more time than triggering the NMI, implying that the slave CPU either runs at |
| 194 | 238 | * a higher clock, or has a way to force the main CPU to wait. |
| 195 | 239 | */ |
| r20326 | r20327 | |
| 238 | 282 | |
| 239 | 283 | READ8_MEMBER(imolagp_state::vreg_data_r) |
| 240 | 284 | { |
| 285 | // auto-steer related |
| 241 | 286 | return 0; |
| 242 | 287 | //return 0xf7; // -> go left? |
| 243 | 288 | //return 0x17; // it checks for this too |
| r20326 | r20327 | |
| 388 | 433 | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) |
| 389 | 434 | |
| 390 | 435 | PORT_START("STEER") |
| 391 | | PORT_BIT( 0x0f, 0x00, IPT_DIAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(1) |
| 436 | PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_MINMAX(0x01, 0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(24) |
| 392 | 437 | INPUT_PORTS_END |
| 393 | 438 | |
| 394 | 439 | |
| r20326 | r20327 | |
| 417 | 462 | |
| 418 | 463 | ***************************************************************************/ |
| 419 | 464 | |
| 420 | | static TIMER_DEVICE_CALLBACK ( imolagp_nmi_cb ) |
| 465 | void imolagp_state::machine_start() |
| 421 | 466 | { |
| 422 | | imolagp_state *state = timer.machine().driver_data<imolagp_state>(); |
| 423 | | int newsteer = timer.machine().root_device().ioport("STEER")->read() & 0xf; |
| 424 | | if (newsteer != state->m_oldsteer) |
| 425 | | { |
| 426 | | if ((newsteer - state->m_oldsteer) & 0x8) |
| 427 | | { |
| 428 | | // shift |
| 429 | | state->m_steerlatch = (state->m_steerlatch << 1) | (~state->m_steerlatch >> 1 & 1); |
| 430 | | state->m_oldsteer = (state->m_oldsteer - 1) & 0xf; |
| 431 | | } |
| 432 | | else |
| 433 | | { |
| 434 | | state->m_oldsteer = (state->m_oldsteer + 1) & 0xf; |
| 435 | | } |
| 436 | | state->m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); |
| 437 | | } |
| 467 | save_item(NAME(m_vcontrol)); |
| 468 | save_item(NAME(m_vreg)); |
| 469 | save_item(NAME(m_scroll)); |
| 470 | save_item(NAME(m_steerlatch)); |
| 471 | save_item(NAME(m_draw_mode)); |
| 472 | save_item(NAME(m_comms_latch)); |
| 438 | 473 | } |
| 439 | 474 | |
| 440 | | INTERRUPT_GEN_MEMBER(imolagp_state::slave_vblank_irq) |
| 475 | void imolagp_state::machine_reset() |
| 441 | 476 | { |
| 442 | | m_scroll = m_vreg[0xe]; // latch scroll |
| 443 | | device.execute().set_input_line(0, HOLD_LINE); |
| 477 | // reset steering wheel |
| 478 | m_steerlatch = 0; |
| 479 | m_steer_pot_timer->adjust(attotime::from_msec(20)); |
| 444 | 480 | } |
| 445 | 481 | |
| 446 | 482 | |
| r20326 | r20327 | |
| 455 | 491 | DEVCB_NULL |
| 456 | 492 | }; |
| 457 | 493 | |
| 458 | | |
| 459 | | void imolagp_state::machine_start() |
| 460 | | { |
| 461 | | save_item(NAME(m_vcontrol)); |
| 462 | | save_item(NAME(m_vreg)); |
| 463 | | save_item(NAME(m_scroll)); |
| 464 | | save_item(NAME(m_steerlatch)); |
| 465 | | save_item(NAME(m_draw_mode)); |
| 466 | | save_item(NAME(m_oldsteer)); |
| 467 | | save_item(NAME(m_comms_latch)); |
| 468 | | } |
| 469 | | |
| 470 | | void imolagp_state::machine_reset() |
| 471 | | { |
| 472 | | } |
| 473 | | |
| 474 | 494 | static MACHINE_CONFIG_START( imolagp, imolagp_state ) |
| 475 | 495 | |
| 476 | 496 | /* basic machine hardware */ |
| r20326 | r20327 | |
| 478 | 498 | MCFG_CPU_PROGRAM_MAP(imolagp_master_map) |
| 479 | 499 | MCFG_CPU_IO_MAP(imolagp_master_io) |
| 480 | 500 | MCFG_CPU_VBLANK_INT_DRIVER("screen", imolagp_state, irq0_line_hold) |
| 481 | | MCFG_TIMER_ADD_PERIODIC("pot_irq", imolagp_nmi_cb, attotime::from_hz(60*3)) |
| 501 | MCFG_TIMER_DRIVER_ADD("pot", imolagp_state, imolagp_pot_callback) // maincpu nmi |
| 482 | 502 | |
| 483 | 503 | MCFG_CPU_ADD("slave", Z80, 4000000) // ? |
| 484 | 504 | MCFG_CPU_PROGRAM_MAP(imolagp_slave_map) |