1 // license:BSD-3-Clause
2 // copyright-holders:Jason Eckhardt, Andrew Gardner, Philip Bennett
3 /*
4 Virtual Combat hardware games.
5 
6 Driver by Jason Eckhardt, Andrew Gardner and Phil Bennett.
7 
8 ----
9 
10 There are two known games on this hardware.  Both are developed by
11 Kyle Hodgetts.
12 
13 Virtual Combat (c) VR8 Inc. 1993
14 http://arcade.sonzogni.com/VRCombat/
15 
16 Shadow Fighters (German) (c) Dutech 1993
17 
18 ----
19 
20 There are two boards to this hardware.  The upper, which contains the
21 graphics ROMs and the i860, and the lower which contains the main
22 and sound CPUs.  Virtual Combat sports two upper boards which
23 output a different rasterization of the scene for each stereo eye.
24 
25 UPPER: (Virtual Combat has an identical MIDDLE board also).
26     Intel I860 XR processor
27     MB8298-25P-SK RAMS x12 (silkscreen said 62256)
28     Analog device ADV476KN50E (silkscreen said BT476)
29     20 MHZ Oscillator
30     8-way DIP switch
31     574200D x4
32     PAL palce24v10 x2 (next to the i860)
33     Bt476 RAMDAC
34 
35 LOWER:
36     Motorola MC68000P12 x2
37     12 MHz Oscillator x2
38     Harris ADC0804LCN x2
39     4 MB8298-25P-SK RAMS (in groups of 2 off by themselves)
40     1 CXK58257SP-10L at each end of the SNDCPU ROMS and the CPU ROMS (4 chips total)
41     Motorola MC6845P CRT controller
42     2x 27C010A containing sound code
43     Xx 27C040 containing sound data (VOC files)
44     Dallas DS1220Y - closest to pin 64 of CPU - read as a 2716 - (silkscreened "6116")
45     Xx 27c040 containing program code, etc.
46 
47 ----
48 
49 NOTES : Shadow Fighters appears to have been dumped from an earlier
50             revision of the hardware.  There are no IC labels, and
51             lots of factory rework has been done to the bottom board.
52         Because the board was so early for Shadow Fighters, there were
53             no IC locations silkscreened on the PCB.  The locations
54             from Virtual Combat have been used.
55         The Shadow Fighters bottom board has an extra 20 mhz xtal on it.
56         The data stored in "samples" is simply a series of
57             Creative Media VOC files concatenated to each other.
58         The sound program ("sound") is about 640 bytes long.
59         The hardware is said to run at medium resolution.
60         The SRAM module dump can likely be thrown away for both games.
61         The PAL that's dumped for Shadow Fighters looks pretty bad.
62 
63 TODO :  This is a partially working driver.  Most of the memory maps for
64             all four CPUs are complete.  An Intel i860XR CPU core has now
65             been incorporated into MAME.
66 
67     --------                Notes/questions                  ----------
68      - Most of the memory maps and input ports are complete now.
69        For "main", the only I/O locations that seem to be left
70        mysterious are:
71          0x60001C: Only read; might be a latch of some sort.  It is
72                read each time M0's interrupt service routine syncs
73                with the i860's to have them update the frame buffer.
74                Might this be a HW blank bit so things look clean when
75                the i860's do their updates?
76                The two other times I see it read are just before
77                and after one of the palette setups is done.
78          0x600018: ? No info yet.
79          0x704000: (VC only) Likely analog axis for VR headset
80          0x703000: (VC only) Likely analog axis for VR headset
81 
82     ----------------------------------------------
83 */
84 
85 #include "emu.h"
86 #include "cpu/i860/i860.h"
87 #include "cpu/m68000/m68000.h"
88 #include "machine/nvram.h"
89 #include "sound/dac.h"
90 #include "video/mc6845.h"
91 #include "video/tlc34076.h"
92 #include "rendlay.h"
93 #include "screen.h"
94 #include "speaker.h"
95 
96 #define VERBOSE 0
97 #include "logmacro.h"
98 
99 
100 class vcombat_state : public driver_device
101 {
102 public:
vcombat_state(const machine_config & mconfig,device_type type,const char * tag)103 	vcombat_state(const machine_config &mconfig, device_type type, const char *tag)
104 		: driver_device(mconfig, type, tag),
105 		m_tlc34076(*this, "tlc34076"),
106 		m_framebuffer_ctrl(*this, "fb_control"),
107 		m_maincpu(*this, "maincpu"),
108 		m_soundcpu(*this, "soundcpu"),
109 		m_vid(*this, "vid_%u", 0U),
110 		m_dac(*this, "dac"),
111 		m_crtc(*this, "crtc") { }
112 
113 	void init_shadfgtr();
114 	void init_vcombat();
115 
116 	void shadfgtr(machine_config &config);
117 	void vcombat(machine_config &config);
118 
119 protected:
120 	virtual void machine_reset() override;
121 
122 private:
123 	required_device<tlc34076_device> m_tlc34076;
124 	required_shared_ptr<uint16_t> m_framebuffer_ctrl;
125 	required_device<cpu_device> m_maincpu;
126 	required_device<cpu_device> m_soundcpu;
127 	optional_device_array<i860_cpu_device, 2> m_vid;
128 	required_device<dac_word_interface> m_dac;
129 	optional_device<mc6845_device> m_crtc;
130 
131 	std::unique_ptr<uint16_t[]> m_m68k_framebuffer[2];
132 	std::unique_ptr<uint16_t[]> m_i860_framebuffer[2][2];
133 	int m_crtc_select;
134 
135 	void main_video_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
136 	uint16_t control_1_r();
137 	uint16_t control_2_r();
138 	uint16_t control_3_r();
139 	void wiggle_i860_common(int which, uint16_t data);
140 	void wiggle_i860p0_pins_w(uint16_t data);
141 	void wiggle_i860p1_pins_w(uint16_t data);
142 	uint16_t main_irqiack_r();
143 	uint16_t sound_resetmain_r();
144 	void v0_fb_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0);
145 	void v1_fb_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0);
146 	void crtc_w(uint16_t data);
147 	void vcombat_dac_w(uint16_t data);
148 	DECLARE_WRITE_LINE_MEMBER(sound_update);
149 
150 	uint32_t update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int index);
151 	uint32_t screen_update_vcombat_main(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
152 	uint32_t screen_update_vcombat_aux(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
153 
154 	void main_map(address_map &map);
155 	void sound_map(address_map &map);
156 	void vid_0_map(address_map &map);
157 	void vid_1_map(address_map &map);
158 };
159 
update_screen(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect,int index)160 uint32_t vcombat_state::update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int index)
161 {
162 	int y;
163 	const pen_t *const pens = m_tlc34076->pens();
164 
165 	uint16_t *m68k_buf = m_m68k_framebuffer[(*m_framebuffer_ctrl & 0x20) ? 1 : 0].get();
166 	uint16_t *i860_buf = m_i860_framebuffer[index][0].get();
167 
168 	/* TODO: It looks like the leftmost chunk of the ground should really be on the right side? */
169 	/*       But the i860 draws the background correctly, so it may be an original game issue. */
170 	/*       There's also some garbage in the upper-left corner. Might be related to this 'wraparound'. */
171 	/*       Or maybe it's related to the 68k's alpha?  It might come from the 68k side of the house.  */
172 
173 	for (y = cliprect.min_y; y <= cliprect.max_y; ++y)
174 	{
175 		int src_addr = 256/2 * y;
176 		const uint16_t *m68k_src = &m68k_buf[src_addr];
177 		const uint16_t *i860_src = &i860_buf[src_addr];
178 		uint32_t *dst = &bitmap.pix(y, cliprect.min_x);
179 
180 		for (int x = cliprect.min_x; x <= cliprect.max_x; x += 2)
181 		{
182 			uint16_t m68k_pix = *m68k_src++;
183 			uint16_t i860_pix = *i860_src++;
184 
185 			/* Draw two pixels */
186 			for (int i = 0; i < 2; ++i)
187 			{
188 				/* Vcombat's screen renders 'flopped' - very likely because VR headset displays may reflect off mirrors.
189 				Shadfgtr isn't flopped, so it's not a constant feature of the hardware. */
190 
191 				/* Combine the two layers */
192 				if ((m68k_pix & 0xff) == 0)
193 					*dst++ = pens[i860_pix & 0xff];
194 				else
195 					*dst++ = pens[m68k_pix & 0xff];
196 
197 				m68k_pix >>= 8;
198 				i860_pix >>= 8;
199 			}
200 		}
201 	}
202 
203 	return 0;
204 }
205 
screen_update_vcombat_main(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)206 uint32_t vcombat_state::screen_update_vcombat_main(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect){ return update_screen(screen, bitmap, cliprect, 0); }
screen_update_vcombat_aux(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)207 uint32_t vcombat_state::screen_update_vcombat_aux(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect){ return update_screen(screen, bitmap, cliprect, 1); }
208 
209 
main_video_write(offs_t offset,uint16_t data,uint16_t mem_mask)210 void vcombat_state::main_video_write(offs_t offset, uint16_t data, uint16_t mem_mask)
211 {
212 	int fb = (*m_framebuffer_ctrl & 0x20) ? 0 : 1;
213 	uint16_t old_data = m_m68k_framebuffer[fb][offset];
214 
215 	/* Transparency mode? */
216 	if (*m_framebuffer_ctrl & 0x40)
217 	{
218 		if (data == 0x0000)
219 			return;
220 
221 		if ((data & 0x00ff) == 0)
222 			data = (data & 0xff00) | (old_data & 0x00ff);
223 		if ((data & 0xff00) == 0)
224 			data = (data & 0x00ff) | (old_data & 0xff00);
225 
226 		COMBINE_DATA(&m_m68k_framebuffer[fb][offset]);
227 	}
228 	else
229 	{
230 		COMBINE_DATA(&m_m68k_framebuffer[fb][offset]);
231 	}
232 }
233 
control_1_r()234 uint16_t vcombat_state::control_1_r()
235 {
236 	return (ioport("IN0")->read() << 8);
237 }
238 
control_2_r()239 uint16_t vcombat_state::control_2_r()
240 {
241 	return (ioport("IN1")->read() << 8);
242 }
243 
control_3_r()244 uint16_t vcombat_state::control_3_r()
245 {
246 	return (ioport("IN2")->read() << 8);
247 }
248 
wiggle_i860_common(int which,uint16_t data)249 void vcombat_state::wiggle_i860_common(int which, uint16_t data)
250 {
251 	int bus_hold = (data & 0x03) == 0x03;
252 	int reset = data & 0x10;
253 	if (!m_vid[which].found())
254 		return;
255 
256 	i860_cpu_device &device = *m_vid[which];
257 	if (bus_hold)
258 	{
259 		LOG("M0 asserting bus HOLD to i860 #%d\n", which);
260 		device.i860_set_pin(DEC_PIN_BUS_HOLD, 1);
261 	}
262 	else
263 	{
264 		LOG("M0 clearing bus HOLD to i860 #%d\n", which);
265 		device.i860_set_pin(DEC_PIN_BUS_HOLD, 0);
266 	}
267 
268 	if (reset)
269 	{
270 		LOG("M0 asserting RESET to i860 #%d\n", which);
271 		device.i860_set_pin(DEC_PIN_RESET, 1);
272 	}
273 	else
274 		device.i860_set_pin(DEC_PIN_RESET, 0);
275 }
276 
wiggle_i860p0_pins_w(uint16_t data)277 void vcombat_state::wiggle_i860p0_pins_w(uint16_t data)
278 {
279 	wiggle_i860_common(0, data);
280 }
281 
wiggle_i860p1_pins_w(uint16_t data)282 void vcombat_state::wiggle_i860p1_pins_w(uint16_t data)
283 {
284 	wiggle_i860_common(1, data);
285 }
286 
main_irqiack_r()287 uint16_t vcombat_state::main_irqiack_r()
288 {
289 	//LOG("M0: irq iack\n");
290 	m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
291 	//m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
292 	return 0;
293 }
294 
sound_resetmain_r()295 uint16_t vcombat_state::sound_resetmain_r()
296 {
297 	//LOG("M1: reset line to M0\n");
298 	//m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
299 	return 0;
300 }
301 
v0_fb_w(offs_t offset,uint64_t data,uint64_t mem_mask)302 void vcombat_state::v0_fb_w(offs_t offset, uint64_t data, uint64_t mem_mask)
303 {
304 	/* The frame buffer seems to sit on a 32-bit data bus, while the
305 	   i860 uses a 64-bit data bus.  Adjust accordingly.  */
306 	char *p = (char *)(m_i860_framebuffer[0][0].get());
307 	int m = mem_mask;
308 	int o = (offset << 2);
309 	if (m & 0xff000000) {
310 		p[o+3] = (data >> 24) & 0xff;
311 	}
312 	if (m & 0x00ff0000) {
313 		p[o+2] = (data >> 16) & 0xff;
314 	}
315 	if (m & 0x0000ff00) {
316 		p[o+1] = (data >> 8) & 0xff;
317 	}
318 	if (m & 0x000000ff) {
319 		p[o+0] = (data >> 0) & 0xff;
320 	}
321 }
322 
323 /* This is just temporary so we can see what each i860 is doing to the
324    framebuffer.  */
v1_fb_w(offs_t offset,uint64_t data,uint64_t mem_mask)325 void vcombat_state::v1_fb_w(offs_t offset, uint64_t data, uint64_t mem_mask)
326 {
327 	/* The frame buffer seems to sit on a 32-bit data bus, while the
328 	   i860 uses a 64-bit data bus.  Adjust accordingly.  */
329 	char *p = (char *)(m_i860_framebuffer[1][0].get());
330 	int m = mem_mask;
331 	int o = (offset << 2);
332 	if (m & 0xff000000) {
333 		p[o+3] = (data >> 24) & 0xff;
334 	}
335 	if (m & 0x00ff0000) {
336 		p[o+2] = (data >> 16) & 0xff;
337 	}
338 	if (m & 0x0000ff00) {
339 		p[o+1] = (data >> 8) & 0xff;
340 	}
341 	if (m & 0x000000ff) {
342 		p[o+0] = (data >> 0) & 0xff;
343 	}
344 }
345 
crtc_w(uint16_t data)346 void vcombat_state::crtc_w(uint16_t data)
347 {
348 	if (m_crtc == nullptr)
349 		return;
350 
351 	if (m_crtc_select == 0)
352 		m_crtc->address_w(data >> 8);
353 	else
354 		m_crtc->register_w(data >> 8);
355 
356 	m_crtc_select ^= 1;
357 }
358 
vcombat_dac_w(uint16_t data)359 void vcombat_state::vcombat_dac_w(uint16_t data)
360 {
361 	m_dac->write(data >> 5);
362 	if (data & 0x801f)
363 		LOG("dac overflow %04x\n", data & 0x801f);
364 }
365 
main_map(address_map & map)366 void vcombat_state::main_map(address_map &map)
367 {
368 	map(0x000000, 0x0fffff).rom();
369 	map(0x200000, 0x20ffff).ram();
370 	map(0x300000, 0x30ffff).w(FUNC(vcombat_state::main_video_write));
371 
372 	map(0x400000, 0x43ffff).ram().share("vid_0_ram");   /* First i860 shared RAM */
373 	map(0x440000, 0x440003).ram().share("share6");      /* M0->P0 i860 #1 com 1 */
374 	map(0x480000, 0x480003).ram().share("share7");      /* M0<-P0 i860 #1 com 2 */
375 	map(0x4c0000, 0x4c0003).w(FUNC(vcombat_state::wiggle_i860p0_pins_w)); /* i860 #1 stop/start/reset */
376 
377 	map(0x500000, 0x53ffff).ram().share("vid_1_ram");   /* Second i860 shared RAM */
378 	map(0x540000, 0x540003).ram().share("share8");      /* M0->P1 i860 #2 com 1 */
379 	map(0x580000, 0x580003).ram().share("share9");      /* M0<-P1 i860 #2 com 2 */
380 	map(0x5c0000, 0x5c0003).w(FUNC(vcombat_state::wiggle_i860p1_pins_w)); /* i860 #2 stop/start/reset */
381 
382 	map(0x600000, 0x600001).r(FUNC(vcombat_state::control_1_r));   /* IN0 port */
383 	map(0x600004, 0x600005).ram().share("share5");      /* M0<-M1 */
384 	map(0x600008, 0x600009).r(FUNC(vcombat_state::control_2_r));   /* IN1 port */
385 	map(0x60001c, 0x60001d).noprw();
386 
387 	map(0x60000c, 0x60000d).w(FUNC(vcombat_state::crtc_w));
388 	map(0x600010, 0x600011).ram().share("fb_control");
389 	map(0x700000, 0x7007ff).ram().share("nvram");
390 	map(0x701000, 0x701001).r(FUNC(vcombat_state::main_irqiack_r));
391 	map(0x702000, 0x702001).r(FUNC(vcombat_state::control_3_r));
392 	map(0x705000, 0x705001).ram().share("share4");      /* M1->M0 */
393 
394 	//map(0x703000, 0x703001)      /* Headset rotation axis? */
395 	//map(0x704000, 0x704001)      /* Headset rotation axis? */
396 
397 	map(0x706000, 0x70601f).rw(m_tlc34076, FUNC(tlc34076_device::read), FUNC(tlc34076_device::write)).umask16(0x00ff);
398 }
399 
400 
401 /* The first i860 - middle board */
vid_0_map(address_map & map)402 void vcombat_state::vid_0_map(address_map &map)
403 {
404 	map(0x00000000, 0x0001ffff).ram().w(FUNC(vcombat_state::v0_fb_w));      /* Shared framebuffer - half of the bits lost to 32-bit bus */
405 	map(0x20000000, 0x20000007).ram().share("share6");      /* M0<-P0 com 1 (0x440000 in 68k-land) */
406 	map(0x40000000, 0x401fffff).rom().region("gfx", 0);
407 	map(0x80000000, 0x80000007).ram().share("share7");      /* M0->P0 com 2 (0x480000 in 68k-land) */
408 	map(0xc0000000, 0xc0000fff).noprw();                     /* Dummy D$ flush page. */
409 	map(0xfffc0000, 0xffffffff).ram().share("vid_0_ram");           /* Shared RAM with main */
410 }
411 
412 
413 /* The second i860 - top board */
vid_1_map(address_map & map)414 void vcombat_state::vid_1_map(address_map &map)
415 {
416 	map(0x00000000, 0x0001ffff).ram().w(FUNC(vcombat_state::v1_fb_w));      /* Half of the bits lost to 32-bit bus */
417 	map(0x20000000, 0x20000007).ram().share("share8");      /* M0->P1 com 1 (0x540000 in 68k-land) */
418 	map(0x40000000, 0x401fffff).rom().region("gfx", 0);
419 	map(0x80000000, 0x80000007).ram().share("share9");          /* M0<-P1 com 2      (0x580000 in 68k-land) */
420 	map(0xc0000000, 0xc0000fff).noprw();                     /* Dummy D$ flush page. */
421 	map(0xfffc0000, 0xffffffff).ram().share("vid_1_ram");           /* Shared RAM with main */
422 }
423 
424 
425 /* Sound CPU */
sound_map(address_map & map)426 void vcombat_state::sound_map(address_map &map)
427 {
428 	map(0x000000, 0x03ffff).rom();
429 	map(0x080000, 0x08ffff).ram();
430 	map(0x0c0000, 0x0c0001).w(FUNC(vcombat_state::vcombat_dac_w));
431 	map(0x140000, 0x140001).r(FUNC(vcombat_state::sound_resetmain_r));   /* Ping M0's reset line */
432 	map(0x180000, 0x180001).ram().share("share4");   /* M1<-M0 */
433 	map(0x1c0000, 0x1c0001).ram().share("share5");   /* M1->M0 */
434 	map(0x200000, 0x37ffff).rom().region("samples", 0);
435 }
436 
437 
machine_reset()438 void vcombat_state::machine_reset()
439 {
440 	for (auto &i860 : m_vid)
441 		if (i860.found())
442 			i860->i860_set_pin(DEC_PIN_BUS_HOLD, 1);
443 
444 	m_crtc_select = 0;
445 }
446 
447 
init_vcombat()448 void vcombat_state::init_vcombat()
449 {
450 	uint8_t *ROM = memregion("maincpu")->base();
451 
452 	/* Allocate the 68000 framebuffers */
453 	m_m68k_framebuffer[0] = std::make_unique<uint16_t[]>(0x8000);
454 	m_m68k_framebuffer[1] = std::make_unique<uint16_t[]>(0x8000);
455 
456 	/* First i860 */
457 	m_i860_framebuffer[0][0] = std::make_unique<uint16_t[]>(0x8000);
458 	m_i860_framebuffer[0][1] = std::make_unique<uint16_t[]>(0x8000);
459 
460 	/* Second i860 */
461 	m_i860_framebuffer[1][0] = std::make_unique<uint16_t[]>(0x8000);
462 	m_i860_framebuffer[1][1] = std::make_unique<uint16_t[]>(0x8000);
463 
464 	/* pc==4016 : jump 4038 ... There's something strange about how it waits at 402e (interrupts all masked out)
465 	   I think what is happening here is that M0 snags the first time
466 	   it hits this point based on a counter test just above this
467 	   instruction.  That counter gets updated just past this instruction.
468 	   However, the only way this can be passed is if the M0 CPU is
469 	   reset (the IPL=7, but irq 7 is a nop).  I am almost sure that M1
470 	   reads a latch, which resets M0 (probably to ensure M0 and M1 are
471 	   both alive) and gets passed this snag.  I tried to hook up a reset
472 	   which should work, but asserting the reset line on the m68k doesn't
473 	   seem to do anything.  Maybe the 68k emulator doesn't respond to
474 	   that, or I didn't do it correctly.  But I think that is what needs
475 	   to be done.  But it isn't crucial for emulation.  Shadow does not
476 	   have this snag. */
477 	ROM[0x4017] = 0x66;
478 }
479 
init_shadfgtr()480 void vcombat_state::init_shadfgtr()
481 {
482 	/* Allocate th 68000 frame buffers */
483 	m_m68k_framebuffer[0] = std::make_unique<uint16_t[]>(0x8000);
484 	m_m68k_framebuffer[1] = std::make_unique<uint16_t[]>(0x8000);
485 
486 	/* Only one i860 */
487 	m_i860_framebuffer[0][0] = std::make_unique<uint16_t[]>(0x8000);
488 	m_i860_framebuffer[0][1] = std::make_unique<uint16_t[]>(0x8000);
489 	m_i860_framebuffer[1][0] = nullptr;
490 	m_i860_framebuffer[1][1] = nullptr;
491 }
492 
493 
494 static INPUT_PORTS_START( vcombat )
495 	PORT_START("IN0")
496 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
497 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )   /* Left button */
498 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )   /* Right button */
499 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
500 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
501 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
502 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
503 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
504 
505 	PORT_START("IN1")
506 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
507 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
508 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
509 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
510 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
511 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
512 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
513 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
514 INPUT_PORTS_END
515 
516 
INPUT_PORTS_START(shadfgtr)517 static INPUT_PORTS_START( shadfgtr )
518 	/* Check me */
519 	PORT_START("IN0")
520 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
521 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
522 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
523 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
524 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_PLAYER(2)
525 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_PLAYER(2)
526 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(2)
527 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(2)
528 
529 	PORT_START("IN1")
530 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
531 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
532 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
533 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
534 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
535 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
536 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
537 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
538 
539 	/* Check me */
540 	PORT_START("IN2")
541 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY
542 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY
543 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
544 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
545 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
546 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
547 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 )
548 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 )
549 INPUT_PORTS_END
550 
551 
552 WRITE_LINE_MEMBER(vcombat_state::sound_update)
553 {
554 	/* Seems reasonable */
555 	m_soundcpu->set_input_line(M68K_IRQ_1, state ? ASSERT_LINE : CLEAR_LINE);
556 }
557 
vcombat(machine_config & config)558 void vcombat_state::vcombat(machine_config &config)
559 {
560 	M68000(config, m_maincpu, XTAL(12'000'000));
561 	m_maincpu->set_addrmap(AS_PROGRAM, &vcombat_state::main_map);
562 	m_maincpu->set_vblank_int("screen", FUNC(vcombat_state::irq1_line_assert));
563 
564 	/* The middle board i860 */
565 	I860(config, m_vid[0], XTAL(20'000'000));
566 	m_vid[0]->set_addrmap(AS_PROGRAM, &vcombat_state::vid_0_map);
567 
568 	/* The top board i860 */
569 	I860(config, m_vid[1], XTAL(20'000'000));
570 	m_vid[1]->set_addrmap(AS_PROGRAM, &vcombat_state::vid_1_map);
571 
572 	/* Sound CPU */
573 	M68000(config, m_soundcpu, XTAL(12'000'000));
574 	m_soundcpu->set_addrmap(AS_PROGRAM, &vcombat_state::sound_map);
575 	m_soundcpu->set_periodic_int(FUNC(vcombat_state::irq1_line_hold), attotime::from_hz(15000)); /* Remove this if MC6845 is enabled */
576 
577 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
578 
579 /* Temporary hack for experimenting with timing. */
580 #if 0
581 	//config.set_maximum_quantum(attotime::from_hz(1200));
582 	config.m_perfect_cpu_quantum = subtag("maincpu");
583 #endif
584 
585 	TLC34076(config, m_tlc34076, tlc34076_device::TLC34076_6_BIT);
586 
587 	/* Disabled for now as it can't handle multiple screens */
588 //  MC6845(config, m_crtc, 6000000 / 16);
589 //  m_crtc->set_screen("screen");
590 	config.set_default_layout(layout_dualhsxs);
591 
592 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
593 	screen.set_raw(XTAL(12'000'000) / 2, 400, 0, 256, 291, 0, 208);
594 	screen.set_screen_update(FUNC(vcombat_state::screen_update_vcombat_main));
595 
596 	screen_device &aux(SCREEN(config, "aux", SCREEN_TYPE_RASTER));
597 	aux.set_raw(XTAL(12'000'000) / 2, 400, 0, 256, 291, 0, 208);
598 	aux.set_screen_update(FUNC(vcombat_state::screen_update_vcombat_aux));
599 
600 	SPEAKER(config, "speaker").front_center();
601 	DAC_10BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
602 }
603 
604 
shadfgtr(machine_config & config)605 void vcombat_state::shadfgtr(machine_config &config)
606 {
607 	M68000(config, m_maincpu, XTAL(12'000'000));
608 	m_maincpu->set_addrmap(AS_PROGRAM, &vcombat_state::main_map);
609 	m_maincpu->set_vblank_int("screen", FUNC(vcombat_state::irq1_line_assert));
610 
611 	/* The middle board i860 */
612 	I860(config, m_vid[0], XTAL(20'000'000));
613 	m_vid[0]->set_addrmap(AS_PROGRAM, &vcombat_state::vid_0_map);
614 
615 	/* Sound CPU */
616 	M68000(config, m_soundcpu, XTAL(12'000'000));
617 	m_soundcpu->set_addrmap(AS_PROGRAM, &vcombat_state::sound_map);
618 
619 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
620 
621 	TLC34076(config, m_tlc34076, tlc34076_device::TLC34076_6_BIT);
622 
623 	MC6845(config, m_crtc, XTAL(20'000'000) / 4 / 16);
624 	m_crtc->set_screen("screen");
625 	m_crtc->set_show_border_area(false);
626 	m_crtc->set_char_width(16);
627 	m_crtc->out_hsync_callback().set(FUNC(vcombat_state::sound_update));
628 
629 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
630 	screen.set_raw(XTAL(20'000'000) / 4, 320, 0, 256, 277, 0, 224);
631 	screen.set_screen_update(FUNC(vcombat_state::screen_update_vcombat_main));
632 
633 	SPEAKER(config, "speaker").front_center();
634 	DAC_10BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
635 }
636 
637 
638 ROM_START( vcombat )
639 	ROM_REGION( 0x100000, "maincpu", 0 )
640 	ROM_LOAD16_BYTE( "ep8v2.b49", 0x00000, 0x80000, CRC(98d5a45d) SHA1(099e314f11c93ad6e642ceaa311e2a5b6fd7193c) )
641 	ROM_LOAD16_BYTE( "ep7v2.b51", 0x00001, 0x80000, CRC(06185bcb) SHA1(855b11ae7644d6c7c1c935b2f5aec484071ca870) )
642 
643 	ROM_REGION( 0x40000, "soundcpu", 0 )
644 	ROM_LOAD16_BYTE( "ep1v2.b42", 0x00000, 0x20000, CRC(560b2e6c) SHA1(e35c0466a1e14beab080e3155f873e9c2a1c028b) )
645 	ROM_LOAD16_BYTE( "ep6v2.b33", 0x00001, 0x20000, CRC(37928a5d) SHA1(7850be26dbd356cdeef2a0d87738de16420f6291) )
646 
647 	ROM_REGION16_BE( 0x180000, "samples", 0 )
648 	ROM_LOAD16_BYTE( "ep2v2.b41", 0x000000, 0x80000, CRC(7dad3458) SHA1(deae5ebef0346250d3f9744933423253a336bb67) )
649 	ROM_LOAD16_BYTE( "ep4v2.b37", 0x000001, 0x80000, CRC(b0be2e91) SHA1(66f3a9f5abeb4b95ac806e4bb165f938dca38b2d) )
650 	ROM_LOAD16_BYTE( "ep3v2.b40", 0x100000, 0x40000, CRC(8c491526) SHA1(95c6bcbe0adcfffb12fd2b86c9f4ca26aa188bbf) )
651 	ROM_LOAD16_BYTE( "ep5v2.b36", 0x100001, 0x40000, CRC(7592b2eb) SHA1(92a540726306d7adbf207fe86a4c4fa66958f90b) )
652 
653 	ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
654 	ROM_LOAD( "ds1220y.b53", 0x000, 0x800, CRC(b21cfe5f) SHA1(898ace3cd0913ea4b0dc84320219777773ef856f) )
655 
656 	/* These roms are identical on both of the upper boards */
657 	ROM_REGION64_LE( 0x200000, "gfx", 0 )
658 	ROM_LOAD64_WORD( "9.u55",  0x000000, 0x80000, CRC(a276e18b) SHA1(6d60e519196a4858b82241504592413df498e12f) )
659 	ROM_LOAD64_WORD( "10.u57", 0x000002, 0x80000, CRC(8921f20e) SHA1(6e9ca2eaad3e1108ba0e1d7792fd5d0305bec201) )
660 	ROM_LOAD64_WORD( "11.u54", 0x000004, 0x80000, CRC(a83094ce) SHA1(c3512375fecdb5e7eb02a4aa140ae4efe0233cb8) )
661 	ROM_LOAD64_WORD( "12.u56", 0x000006, 0x80000, CRC(0cdffd4f) SHA1(65ace78711b3ef6e0ff9a7ad7343b5558e652f6c) )
662 
663 	ROM_REGION( 0x400, "plds", 0 )
664 	ROM_LOAD( "pal1_w2.u51", 0x000, 0x1f1, CRC(af497420) SHA1(03aa82189d91ae194dd5a6e7b9dbdb7cd473ddb6) )
665 	ROM_LOAD( "pal2_w2.u52", 0x200, 0x1f1, CRC(4a6df05d) SHA1(236b951e5daf927c050d0f35558c171a020156ab) )
666 ROM_END
667 
668 ROM_START( shadfgtr )
669 	ROM_REGION( 0x100000, "maincpu", 0 )
670 	ROM_LOAD16_BYTE( "shadfgtr.b49", 0x00000, 0x80000, CRC(2d9d31a1) SHA1(45854915bcb9db2e4076a7f26a0a349077cd10bc) )
671 	ROM_LOAD16_BYTE( "shadfgtr.b51", 0x00001, 0x80000, CRC(03d0f075) SHA1(06013a4363305a23d7e8ba8fe2fa961cd540391d) )
672 
673 	ROM_REGION( 0x40000, "soundcpu", 0 )
674 	ROM_LOAD16_BYTE( "shadfgtr.b42", 0x00000, 0x20000, CRC(f8605dcd) SHA1(1b29f47856ccc757bc96674682ae48f87e6b0e54) )
675 	ROM_LOAD16_BYTE( "shadfgtr.b33", 0x00001, 0x20000, CRC(291d59ac) SHA1(cc4904c2ac8ef6a12033c10893246a438ac44014) )
676 
677 	ROM_REGION16_BE( 0x180000, "samples", 0 )
678 	ROM_LOAD16_BYTE( "shadfgtr.b41", 0x00000, 0x80000, CRC(9e4b4df3) SHA1(8101197275e9f728acdeef85737eecbdec132b27) )
679 	ROM_LOAD16_BYTE( "shadfgtr.b37", 0x00001, 0x80000, CRC(98446ba2) SHA1(1c8cc0d9c5de54d9e53699a5ab281579d15edc96) )
680 
681 	ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
682 	ROM_LOAD( "shadfgtr.b53", 0x000, 0x800, CRC(e766a3ab) SHA1(e7696ec08d5c86f64d768480f43edbd19ded162d) )
683 
684 	ROM_REGION64_LE( 0x200000, "gfx", 0 )
685 	ROM_LOAD64_WORD( "shadfgtr.u55", 0x000000, 0x80000, CRC(e807631d) SHA1(9027ff7dc60b808434dac292c08f0630d3d52186) )
686 	ROM_LOAD64_WORD( "shadfgtr.u57", 0x000002, 0x80000, CRC(60d701d7) SHA1(936473b5e3b2e9e9e3b50cf977fc5a670a097850) )
687 	ROM_LOAD64_WORD( "shadfgtr.u54", 0x000004, 0x80000, CRC(c45d68d6) SHA1(a133e4f13d3af18bccf0d060a659d64ac699b159) )
688 	ROM_LOAD64_WORD( "shadfgtr.u56", 0x000006, 0x80000, CRC(fb76db5a) SHA1(fa546f465df113c13037abed1162bfa6f9b1dc9b) )
689 
690 	ROM_REGION( 0x200, "plds", 0 )
691 	ROM_LOAD( "shadfgtr.u51", 0x000, 0x1f1, CRC(bab58337) SHA1(c4a79c8e53aeadb7f64d49d214b607b5b36f144e) )
692 	/* The second upper-board PAL couldn't be read */
693 ROM_END
694 
695 //    YEAR  NAME      PARENT  MACHINE   INPUT     STATE          INIT      MONITOR              COMPANY         FULLNAME           FLAGS
696 GAME( 1993, vcombat,  0,      vcombat,  vcombat,  vcombat_state, init_vcombat,  ORIENTATION_FLIP_X,  "VR8 Inc.",     "Virtual Combat",  MACHINE_NOT_WORKING )
697 GAME( 1993, shadfgtr, 0,      shadfgtr, shadfgtr, vcombat_state, init_shadfgtr, ROT0,                "Dutech Inc.",  "Shadow Fighters", MACHINE_NOT_WORKING )
698