1 // license:GPL-2.0+
2 // copyright-holders:Jarek Burczynski, Phil Stroffolino, Tomasz Slanina
3 /**************************************************************************
4 Change Lanes
5 (C) Taito 1983
6
7 Jarek Burczynski
8 Phil Stroffolino
9 Tomasz Slanina
10
11 ***************************************************************************/
12
13 #include "emu.h"
14 #include "includes/changela.h"
15
16 #include "cpu/z80/z80.h"
17 #include "machine/74259.h"
18 #include "machine/watchdog.h"
19 #include "sound/ay8910.h"
20 #include "speaker.h"
21
22 #include "changela.lh"
23
24
mcu_r()25 uint8_t changela_state::mcu_r()
26 {
27 //osd_printf_debug("Z80 MCU R = %x\n", m_mcu_out);
28 return m_mcu_out;
29 }
30
31 /* latch LS374 at U39 */
mcu_w(uint8_t data)32 void changela_state::mcu_w(uint8_t data)
33 {
34 m_mcu_in = data;
35 if (!BIT(m_port_c_out, 2))
36 m_mcu->pa_w(data);
37 }
38
39
40 /*********************************
41 MCU
42 *********************************/
43
changela_68705_port_a_w(uint8_t data)44 void changela_state::changela_68705_port_a_w(uint8_t data)
45 {
46 m_port_a_out = data;
47 }
48
changela_68705_port_c_w(uint8_t data)49 void changela_state::changela_68705_port_c_w(uint8_t data)
50 {
51 /* PC3 is connected to the CLOCK input of the LS374, so we latch the data on rising edge */
52 if (BIT(data, 3) && ~BIT(m_port_c_out, 3))
53 m_mcu_out = m_port_a_out & (BIT(m_port_c_out, 2) ? 0xff : m_mcu_in);
54
55 /* PC2 is connected to the /OE input of the LS374 */
56 if (BIT(data, 2))
57 m_mcu->pa_w(BIT(data, 2) ? 0xff : m_mcu_in);
58
59 m_port_c_out = data;
60 }
61
62
63
64 /* U30 */
changela_24_r()65 uint8_t changela_state::changela_24_r()
66 {
67 return (BIT(m_port_c_out, 1) << 3) | 0x07; /* bits 2,1,0-N/C inputs */
68 }
69
changela_25_r()70 uint8_t changela_state::changela_25_r()
71 {
72 //collisions on bits 3,2, bits 1,0-N/C inputs
73 return (m_tree1_col << 3) | (m_tree0_col << 2) | 0x03;
74 }
75
changela_30_r()76 uint8_t changela_state::changela_30_r()
77 {
78 return ioport("WHEEL")->read() & 0x0f; //wheel control (clocked input) signal on bits 3,2,1,0
79 }
80
changela_31_r()81 uint8_t changela_state::changela_31_r()
82 {
83 /* If the new value is less than the old value, and it did not wrap around,
84 or if the new value is greater than the old value, and it did wrap around,
85 then we are moving LEFT. */
86 uint8_t curr_value = ioport("WHEEL")->read();
87
88 if ((curr_value < m_prev_value_31 && (m_prev_value_31 - curr_value) < 0x80)
89 || (curr_value > m_prev_value_31 && (curr_value - m_prev_value_31) > 0x80))
90 m_dir_31 = 1;
91 if ((m_prev_value_31 < curr_value && (curr_value - m_prev_value_31) < 0x80)
92 || (m_prev_value_31 > curr_value && (m_prev_value_31 - curr_value) > 0x80))
93 m_dir_31 = 0;
94
95 m_prev_value_31 = curr_value;
96
97 //wheel UP/DOWN control signal on bit 3, collisions on bits:2,1,0
98 return (m_dir_31 << 3) | (m_left_bank_col << 2) | (m_right_bank_col << 1) | m_boat_shore_col;
99 }
100
changela_2c_r()101 uint8_t changela_state::changela_2c_r()
102 {
103 int val = ioport("IN0")->read();
104
105 val = (val & 0x30) | ((val & 1) << 7) | (((val & 1) ^ 1) << 6);
106
107 return val;
108 }
109
changela_2d_r()110 uint8_t changela_state::changela_2d_r()
111 {
112 /* the schems are unreadable - I'm not sure it is V8 (page 74, SOUND I/O BOARD SCHEMATIC 1 OF 2, FIGURE 24 - in the middle on the right side) */
113 int v8 = 0;
114 int gas;
115
116 if ((m_screen->vpos() & 0xf8) == 0xf8)
117 v8 = 1;
118
119 /* Gas pedal is made up of 2 switches, 1 active low, 1 active high */
120 switch (ioport("IN1")->read() & 0x03)
121 {
122 case 0x02:
123 gas = 0x80;
124 break;
125 case 0x01:
126 gas = 0x00;
127 break;
128 default:
129 gas = 0x40;
130 break;
131 }
132
133 return (ioport("IN1")->read() & 0x20) | gas | (v8 << 4);
134 }
135
WRITE_LINE_MEMBER(changela_state::mcu_pc_0_w)136 WRITE_LINE_MEMBER(changela_state::mcu_pc_0_w)
137 {
138 m_mcu->pc_w(0xfe | state);
139 }
140
WRITE_LINE_MEMBER(changela_state::collision_reset_0_w)141 WRITE_LINE_MEMBER(changela_state::collision_reset_0_w)
142 {
143 m_collision_reset = state;
144 }
145
WRITE_LINE_MEMBER(changela_state::collision_reset_1_w)146 WRITE_LINE_MEMBER(changela_state::collision_reset_1_w)
147 {
148 m_tree_collision_reset = state;
149 }
150
WRITE_LINE_MEMBER(changela_state::coin_counter_1_w)151 WRITE_LINE_MEMBER(changela_state::coin_counter_1_w)
152 {
153 machine().bookkeeping().coin_counter_w(0, state);
154 }
155
WRITE_LINE_MEMBER(changela_state::coin_counter_2_w)156 WRITE_LINE_MEMBER(changela_state::coin_counter_2_w)
157 {
158 machine().bookkeeping().coin_counter_w(1, state);
159 }
160
161
changela_map(address_map & map)162 void changela_state::changela_map(address_map &map)
163 {
164 map(0x0000, 0x7fff).rom();
165 map(0x8000, 0x83ff).ram().share("spriteram"); /* OBJ0 RAM */
166 map(0x9000, 0x97ff).ram().share("videoram"); /* OBJ1 RAM */
167 map(0xa000, 0xa07f).w(FUNC(changela_state::changela_colors_w)).share("colorram"); /* Color 93419 RAM 64x9(nine!!!) bits A0-used as the 8-th bit data input (d0-d7->normal, a0->d8) */
168 map(0xb000, 0xbfff).rom();
169
170 map(0xc000, 0xc7ff).rw(FUNC(changela_state::changela_mem_device_r), FUNC(changela_state::changela_mem_device_w)); /* RAM4 (River Bed RAM); RAM5 (Tree RAM) */
171
172 /* LS138 - U16 */
173 map(0xc800, 0xc800).nopw(); /* not connected */
174 map(0xc900, 0xc900).w(FUNC(changela_state::changela_mem_device_select_w)); /* selects the memory device to be accessible at 0xc000-0xc7ff */
175 map(0xca00, 0xca00).w(FUNC(changela_state::changela_slope_rom_addr_hi_w));
176 map(0xcb00, 0xcb00).w(FUNC(changela_state::changela_slope_rom_addr_lo_w));
177
178 map(0xd000, 0xd001).rw("ay1", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_data_w));
179 map(0xd010, 0xd011).rw("ay2", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_data_w));
180
181 /* LS259 - U44 */
182 map(0xd020, 0xd027).w("outlatch", FUNC(ls259_device::write_d0));
183
184 /* LS139 - U24 */
185 map(0xd024, 0xd024).r(FUNC(changela_state::changela_24_r));
186 map(0xd025, 0xd025).r(FUNC(changela_state::changela_25_r));
187 map(0xd028, 0xd028).r(FUNC(changela_state::mcu_r));
188 map(0xd02c, 0xd02c).r(FUNC(changela_state::changela_2c_r));
189 map(0xd02d, 0xd02d).r(FUNC(changela_state::changela_2d_r));
190
191 map(0xd030, 0xd030).rw(FUNC(changela_state::changela_30_r), FUNC(changela_state::mcu_w));
192 map(0xd031, 0xd031).r(FUNC(changela_state::changela_31_r));
193
194 map(0xe000, 0xe000).w("watchdog", FUNC(watchdog_timer_device::reset_w)); /* Watchdog */
195
196 map(0xf000, 0xf7ff).ram(); /* RAM2 (Processor RAM) */
197 }
198
199
200 static INPUT_PORTS_START( changela )
201 PORT_START("DSWA") /* DSWA */
202 PORT_DIPNAME( 0x07, 0x01, "Steering Wheel Ratio" ) PORT_DIPLOCATION("SWA:1,2,3")
203 //PORT_DIPSETTING( 0x00, "?" ) /* Not documented */
204 PORT_DIPSETTING( 0x01, "Recommended Setting" )
205 //PORT_DIPSETTING( 0x02, "?" ) /* Not documented */
206 //PORT_DIPSETTING( 0x03, "?" ) /* Not documented */
207 //PORT_DIPSETTING( 0x04, "?" ) /* Not documented */
208 //PORT_DIPSETTING( 0x05, "?" ) /* Not documented */
209 //PORT_DIPSETTING( 0x06, "?" ) /* Not documented */
210 //PORT_DIPSETTING( 0x07, "?" ) /* Not documented */
DEF_STR(Demo_Sounds)211 PORT_DIPNAME( 0x08, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SWA:4")
212 PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
213 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
214 PORT_DIPNAME( 0x10, 0x00, "Ignore Memory Failures" ) PORT_DIPLOCATION("SWA:5")
215 PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
216 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
217 PORT_DIPNAME( 0x20, 0x00, DEF_STR( Controls ) ) PORT_DIPLOCATION("SWA:6")
218 PORT_DIPSETTING( 0x20, DEF_STR( Joystick ) )
219 PORT_DIPSETTING( 0x00, "Steering Wheel" )
220 PORT_DIPNAME( 0x40, 0x40, "Diagnostic" ) PORT_DIPLOCATION("SWA:7")
221 PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
222 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
223 PORT_DIPNAME( 0x80, 0x00, DEF_STR( Players ) ) PORT_DIPLOCATION("SWA:8")
224 PORT_DIPSETTING( 0x80, "1" )
225 PORT_DIPSETTING( 0x00, "2" )
226
227 PORT_START("DSWB") /* DSWB */
228 PORT_DIPNAME( 0x03, 0x00, "Max Bonus Fuels" ) PORT_DIPLOCATION("SWB:1,2")
229 PORT_DIPSETTING( 0x01, "1" )
230 PORT_DIPSETTING( 0x02, "2" )
231 PORT_DIPSETTING( 0x03, "3" )
232 PORT_DIPSETTING( 0x00, "99" )
233 PORT_DIPNAME( 0x0c, 0x08, "Game Difficulty" ) PORT_DIPLOCATION("SWB:3,4")
234 PORT_DIPSETTING( 0x00, DEF_STR( Very_Easy) )
235 PORT_DIPSETTING( 0x04, DEF_STR( Easy ) )
236 PORT_DIPSETTING( 0x08, DEF_STR( Medium ) )
237 PORT_DIPSETTING( 0x0c, DEF_STR( Hard ) )
238 PORT_DIPNAME( 0x30, 0x20, "Traffic Difficulty" ) PORT_DIPLOCATION("SWB:5,6")
239 PORT_DIPSETTING( 0x00, DEF_STR( Very_Easy) )
240 PORT_DIPSETTING( 0x10, DEF_STR( Easy ) )
241 PORT_DIPSETTING( 0x20, DEF_STR( Medium ) )
242 PORT_DIPSETTING( 0x30, DEF_STR( Hard ) )
243 PORT_DIPNAME( 0x40, 0x00, "Land Collisions Enabled" ) PORT_DIPLOCATION("SWB:7")
244 PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
245 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
246 PORT_DIPNAME( 0x80, 0x00, "Car Collision Enabled" ) PORT_DIPLOCATION("SWB:8")
247 PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
248 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
249
250 PORT_START("DSWC") /* DSWC - coinage */
251 PORT_DIPNAME( 0xf0, 0x10, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SWC:5,6,7,8")
252 PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
253 PORT_DIPSETTING( 0x90, DEF_STR( 2C_1C ) )
254 PORT_DIPSETTING( 0xa0, DEF_STR( 2C_2C ) )
255 PORT_DIPSETTING( 0x10, DEF_STR( 1C_1C ) )
256 PORT_DIPSETTING( 0xb0, DEF_STR( 2C_3C ) )
257 PORT_DIPSETTING( 0xc0, DEF_STR( 2C_4C ) )
258 PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) )
259 PORT_DIPSETTING( 0xd0, DEF_STR( 2C_5C ) )
260 PORT_DIPSETTING( 0xe0, DEF_STR( 2C_6C ) )
261 PORT_DIPSETTING( 0x30, DEF_STR( 1C_3C ) )
262 PORT_DIPSETTING( 0xf0, DEF_STR( 2C_7C ) )
263 PORT_DIPSETTING( 0x40, DEF_STR( 1C_4C ) )
264 PORT_DIPSETTING( 0x50, DEF_STR( 1C_5C ) )
265 PORT_DIPSETTING( 0x60, DEF_STR( 1C_6C ) )
266 PORT_DIPSETTING( 0x70, DEF_STR( 1C_7C ) )
267 PORT_DIPNAME( 0x0f, 0x01, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SWC:1,2,3,4")
268 PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
269 PORT_DIPSETTING( 0x09, DEF_STR( 2C_1C ) )
270 PORT_DIPSETTING( 0x0a, DEF_STR( 2C_2C ) )
271 PORT_DIPSETTING( 0x01, DEF_STR( 1C_1C ) )
272 PORT_DIPSETTING( 0x0b, DEF_STR( 2C_3C ) )
273 PORT_DIPSETTING( 0x0c, DEF_STR( 2C_4C ) )
274 PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
275 PORT_DIPSETTING( 0x0d, DEF_STR( 2C_5C ) )
276 PORT_DIPSETTING( 0x0e, DEF_STR( 2C_6C ) )
277 PORT_DIPSETTING( 0x03, DEF_STR( 1C_3C ) )
278 PORT_DIPSETTING( 0x0f, DEF_STR( 2C_7C ) )
279 PORT_DIPSETTING( 0x04, DEF_STR( 1C_4C ) )
280 PORT_DIPSETTING( 0x05, DEF_STR( 1C_5C ) )
281 PORT_DIPSETTING( 0x06, DEF_STR( 1C_6C ) )
282 PORT_DIPSETTING( 0x07, DEF_STR( 1C_7C ) )
283
284 PORT_START("DSWD") /* DSWD - bonus */
285 PORT_DIPNAME( 0x01, 0x01, "Right Slot" ) PORT_DIPLOCATION("SWD:1")
286 PORT_DIPSETTING( 0x01, "On Right (Bottom) Counter" )
287 PORT_DIPSETTING( 0x00, "On Left (Top) Counter" )
288 PORT_DIPNAME( 0x02, 0x00, "Left Slot" ) PORT_DIPLOCATION("SWD:2")
289 PORT_DIPSETTING( 0x02, "On Right (Bottom) Counter" )
290 PORT_DIPSETTING( 0x00, "On Left (Top) Counter" )
291 PORT_DIPNAME( 0x1c, 0x00, "Credits For Bonus" ) PORT_DIPLOCATION("SWD:3,4,5")
292 PORT_DIPSETTING( 0x00, "0" )
293 PORT_DIPSETTING( 0x04, "1" )
294 PORT_DIPSETTING( 0x08, "2" )
295 PORT_DIPSETTING( 0x0c, "3" )
296 PORT_DIPSETTING( 0x10, "4" )
297 PORT_DIPSETTING( 0x14, "5" )
298 PORT_DIPSETTING( 0x18, "6" )
299 PORT_DIPSETTING( 0x1c, "7" )
300 PORT_DIPUNUSED_DIPLOC( 0x20, IP_ACTIVE_LOW, "SWD:6" ) /* Listed as "Unused" */
301 PORT_DIPNAME( 0x40, 0x00, "'King Of The World' Name Length" )PORT_DIPLOCATION("SWD:7")
302 PORT_DIPSETTING( 0x40, "3 Letters" )
303 PORT_DIPSETTING( 0x00, "Long" )
304 PORT_DIPNAME( 0x80, 0x00, "'King Of The World' Name" ) PORT_DIPLOCATION("SWD:8")
305 PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
306 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
307
308 PORT_START("MCU") /* MCU */
309 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
310 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
311 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE )
312 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
313 #ifdef THREE_STATE_SWITCH
314 PORT_DIPNAME( 0x30, 0x30, "Self Test Switch" ) PORT_DIPLOCATION("SWT:1,2")
315 //PORT_DIPSETTING( 0x00, "?" ) /* Not possible, 3-state switch */
316 PORT_DIPSETTING( 0x20, "Free Game" ) /* "Puts a credit on the game without increasing the coin counter." */
317 PORT_DIPSETTING( 0x10, DEF_STR( Test ) )
318 PORT_DIPSETTING( 0x30, DEF_STR( Off ) )
319 #else // schematics don't make it clear exactly how this switch is supposed to work
320 PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Free Game/Self-Test")
321 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
322 #endif
323 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
324 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 )
325
326 PORT_START("IN0") /* 0xDx2C */
327 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Gear Shift") PORT_TOGGLE /* Gear shift */
328 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("DSWA", 0x20, EQUALS, 0x20)
329 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("DSWA", 0x20, EQUALS, 0x20)
330 PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* FWD - negated bit 7 */
331 PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) /* REV - gear position */
332
333 PORT_START("IN1") /* 0xDx2D */
334 PORT_BIT( 0x03, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00, 0x02) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) //gas pedal
335 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
336 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_TILT )
337 //PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) //gas1
338 //PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) //gas2
339
340 PORT_START("WHEEL") /* 0xDx30 DRIVING_WHEEL */
341 PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(50) PORT_KEYDELTA(8) PORT_CONDITION("DSWA", 0x20, EQUALS, 0x00)
342 INPUT_PORTS_END
343
344 TIMER_DEVICE_CALLBACK_MEMBER(changela_state::changela_scanline)
345 {
346 int scanline = param;
347
348 if(scanline == 256) // vblank irq
349 m_maincpu->set_input_line_and_vector(0, HOLD_LINE,0xdf); // Z80
350 else if(((scanline % 64) == 0)) // timer irq, 3 times per given vblank field
351 m_maincpu->set_input_line_and_vector(0, HOLD_LINE,0xcf); // Z80
352 }
353
INTERRUPT_GEN_MEMBER(changela_state::chl_mcu_irq)354 INTERRUPT_GEN_MEMBER(changela_state::chl_mcu_irq)
355 {
356 m_mcu->pulse_input_line(0, m_mcu->minimum_quantum_time());
357 }
358
machine_start()359 void changela_state::machine_start()
360 {
361 /* video */
362 save_item(NAME(m_slopeROM_bank));
363 save_item(NAME(m_tree_en));
364 save_item(NAME(m_horizon));
365 save_item(NAME(m_mem_dev_selected));
366 save_item(NAME(m_v_count_river));
367 save_item(NAME(m_v_count_tree));
368 save_item(NAME(m_tree_on));
369
370 /* mcu */
371 save_item(NAME(m_port_a_out));
372 save_item(NAME(m_port_c_out));
373 save_item(NAME(m_mcu_out));
374 save_item(NAME(m_mcu_in));
375
376 /* misc */
377 save_item(NAME(m_tree0_col));
378 save_item(NAME(m_tree1_col));
379 save_item(NAME(m_left_bank_col));
380 save_item(NAME(m_right_bank_col));
381 save_item(NAME(m_boat_shore_col));
382 save_item(NAME(m_collision_reset));
383 save_item(NAME(m_tree_collision_reset));
384 save_item(NAME(m_prev_value_31));
385 save_item(NAME(m_dir_31));
386
387 m_port_a_out = 0xff;
388 m_port_c_out = 0xff;
389 }
390
machine_reset()391 void changela_state::machine_reset()
392 {
393 /* video */
394 m_slopeROM_bank = 0;
395 m_tree_en = 0;
396 m_horizon = 0;
397 m_mem_dev_selected = 0;
398 m_v_count_river = 0;
399 m_v_count_tree = 0;
400 m_tree_on[0] = 0;
401 m_tree_on[1] = 0;
402
403 /* mcu */
404 m_mcu_out = 0;
405 m_mcu_in = 0;
406
407 /* misc */
408 m_tree0_col = 0;
409 m_tree1_col = 0;
410 m_left_bank_col = 0;
411 m_right_bank_col = 0;
412 m_boat_shore_col = 0;
413 m_collision_reset = 0;
414 m_tree_collision_reset = 0;
415 m_prev_value_31 = 0;
416 m_dir_31 = 0;
417 }
418
changela(machine_config & config)419 void changela_state::changela(machine_config &config)
420 {
421 Z80(config, m_maincpu, 5000000);
422 m_maincpu->set_addrmap(AS_PROGRAM, &changela_state::changela_map);
423 TIMER(config, "scantimer").configure_scanline(FUNC(changela_state::changela_scanline), "screen", 0, 1);
424
425 M68705P3(config, m_mcu, 2500000);
426 m_mcu->portb_r().set_ioport("MCU");
427 m_mcu->porta_w().set(FUNC(changela_state::changela_68705_port_a_w));
428 m_mcu->portc_w().set(FUNC(changela_state::changela_68705_port_c_w));
429 m_mcu->set_vblank_int("screen", FUNC(changela_state::chl_mcu_irq));
430
431 ls259_device &outlatch(LS259(config, "outlatch")); // U44 on Sound I/O Board
432 outlatch.q_out_cb<0>().set(FUNC(changela_state::collision_reset_0_w));
433 outlatch.q_out_cb<1>().set(FUNC(changela_state::coin_counter_1_w));
434 outlatch.q_out_cb<2>().set(FUNC(changela_state::coin_counter_2_w));
435 outlatch.q_out_cb<4>().set(FUNC(changela_state::mcu_pc_0_w));
436 outlatch.q_out_cb<5>().set(FUNC(changela_state::collision_reset_1_w));
437
438 WATCHDOG_TIMER(config, "watchdog");
439
440 SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
441 m_screen->set_refresh_hz(60);
442 m_screen->set_size(32*8, 262); /* vert size is a guess */
443 m_screen->set_visarea(0*8, 32*8-1, 4*8, 32*8-1);
444 m_screen->set_screen_update(FUNC(changela_state::screen_update_changela));
445 m_screen->set_palette(m_palette);
446
447 PALETTE(config, m_palette).set_entries(0x40);
448
449 SPEAKER(config, "mono").front_center();
450
451 ay8910_device &ay1(AY8910(config, "ay1", 1250000));
452 ay1.port_a_read_callback().set_ioport("DSWA");
453 ay1.port_b_read_callback().set_ioport("DSWB");
454 ay1.add_route(ALL_OUTPUTS, "mono", 0.50);
455
456 ay8910_device &ay2(AY8910(config, "ay2", 1250000));
457 ay2.port_a_read_callback().set_ioport("DSWC");
458 ay2.port_b_read_callback().set_ioport("DSWD");
459 ay2.add_route(ALL_OUTPUTS, "mono", 0.50);
460 }
461
462
463 ROM_START( changela )
464 ROM_REGION( 0x10000, "maincpu", 0 ) /* Z80 code */
465 ROM_LOAD( "cl25a", 0x0000, 0x2000, CRC(38530a60) SHA1(0b0ef1abe11c5271fcd1671322b77165217553c3) )
466 ROM_LOAD( "cl24a", 0x2000, 0x2000, CRC(2fcf4a82) SHA1(c33355e2d4d3fab32c8d713a680ec0fceedab341) )
467 ROM_LOAD( "cl23", 0x4000, 0x2000, CRC(08385891) SHA1(d8d66664ec25db067d5a4a6c35ec0ac65b9e0c6a) )
468 ROM_LOAD( "cl22", 0x6000, 0x2000, CRC(796e0abd) SHA1(64dd9fc1f9bc44519a253ef0c02e181dd13904bf) )
469 ROM_LOAD( "cl27", 0xb000, 0x1000, CRC(3668afb8) SHA1(bcfb788baf806edcb129ea9f9dcb1d4260684773) )
470
471 ROM_REGION( 0x00800, "mcu", 0 ) /* 68705P3 */
472 ROM_LOAD( "cl38a", 0x0000, 0x800, CRC(b70156ce) SHA1(c5eab8bbd65c4f587426298da4e22f991ce01dde) )
473
474 ROM_REGION( 0x4000, "gfx1", 0 ) /* tile data */
475 ROM_LOAD( "cl111", 0x0000, 0x2000, CRC(41c0149d) SHA1(3ea53a3821b044b3d0451fec1b4ee2c28da393ca) )
476 ROM_LOAD( "cl113", 0x2000, 0x2000, CRC(ddf99926) SHA1(e816b88302c5639c7284f4845d450f232d63a10c) )
477
478 ROM_REGION( 0x1000, "gfx2", 0 ) /* obj 1 data */
479 ROM_LOAD( "cl46", 0x0000, 0x1000, CRC(9c0a7d28) SHA1(fac9180ea0d9aeea56a84b35cc0958f0dd86a801) )
480
481 ROM_REGION( 0x8000, "user1", 0 ) /* obj 0 data */
482 ROM_LOAD( "cl100", 0x0000, 0x2000, CRC(3fa9e4fa) SHA1(9abd7df5fcf143a0c476bd8c8753c5ea294b9f74) )
483 ROM_LOAD( "cl99", 0x2000, 0x2000, CRC(67b27b9e) SHA1(7df0f93851959359218c8d2272e30d242a77039d) )
484 ROM_LOAD( "cl98", 0x4000, 0x2000, CRC(bffe4149) SHA1(5cf0b98f9d342bd06d575c565ea01bbd79f5e04b) )
485 ROM_LOAD( "cl97", 0x6000, 0x2000, CRC(5abab8f9) SHA1(f5156855bbcdf0740fd44520386318ee53ebbf9a) )
486
487 ROM_REGION( 0x1000, "user2", 0 ) /* math tables: SLOPE ROM (river-tree schematic page 1/3) */
488 ROM_LOAD( "cl44", 0x0000, 0x1000, CRC(160d2bc7) SHA1(2609208c2bd4618ea340923ee01af69278980c36) ) /* first and 2nd half identical */
489
490 ROM_REGION( 0x3000, "user3", 0 ) /* math tables: TREE ROM (river-tree schematic page 3/3)*/
491 ROM_LOAD( "cl7", 0x0000, 0x0800, CRC(01e3efca) SHA1(b26203787f105ba32773e37035c39253050f9c82) ) /* fixed bits: 0xxxxxxx */
492 ROM_LOAD( "cl9", 0x1000, 0x2000, CRC(4e53cdd0) SHA1(6255411cfdccbe2c581c83f9127d582623453c3a) )
493
494 ROM_REGION( 0x0020, "proms", 0 )
495 ROM_LOAD( "cl88", 0x0000, 0x0020, CRC(da4d6625) SHA1(2d9a268973518252eb36f479ab650af8c16c885c) ) /* math train state machine */
496 ROM_END
497
498 GAMEL( 1983, changela, 0, changela, changela, changela_state, empty_init, ROT180, "Taito Corporation", "Change Lanes", MACHINE_SUPPORTS_SAVE, layout_changela )
499