summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/wpc_out.cpp
blob: 5a8941efab917e353bd9e306f9ca84c316d261c7 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                     
                                                                                                    
 
                                                                                                                 
                                                     
 
                        
























                                                         
                                                












                                                          
                                                               




                                                      
                                                  

                     
                                                                 



                                    
                                
                                            










































                                                                         
                                                                       


























                                                                                             
                                                                        


                               
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert

#include "emu.h"
#include "wpc_out.h"

DEFINE_DEVICE_TYPE(WPC_OUT, wpc_out_device, "wpc_out", "Williams Pinball Controller Output Control")

wpc_out_device::wpc_out_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, WPC_OUT, tag, owner, clock)
{
	names = nullptr;
}

wpc_out_device::~wpc_out_device()
{
}

void wpc_out_device::set_names(const char *const *_names)
{
	names = _names;
}

void wpc_out_device::set_handler(handler_t cb)
{
	handler_cb = cb;
}

void wpc_out_device::set_gi_count(int _count)
{
	gi_count = _count;
}

void wpc_out_device::gi_update()
{
	attotime now = machine().time();
	attotime delta = now - previous_gi_update;
	uint32_t delta_us = delta.as_ticks(1e6);
	for(int i=0; i<gi_count; i++)
		if(gi & (1 <<i))
			gi_time[i] += delta_us;
	previous_gi_update = now;
}

void wpc_out_device::send_output(int sid, int state)
{
	if(!handler_cb.isnull() && handler_cb(sid, state))
		return;

	char buffer[32];
	const char *name;
	if(names && names[sid-1] && strcmp(names[sid-1], "s:"))
		name = names[sid-1];
	else {
		sprintf(buffer, "u:output %02d", sid);
		name = buffer;
	}
	machine().output().set_value(name, state);

	if(sid == 41)
		machine().bookkeeping().coin_counter_w(0, state);
}

WRITE8_MEMBER(wpc_out_device::out_w)
{
	first_after_led = false;
	uint8_t diff = state[offset] ^ data;
	state[offset] = data;
	if(diff)
		for(int i=0; i<8; i++)
			if(diff & (1 << i)) {
				int id = (offset << 3) | i;
				int sid;
				if(id <= 3)
					sid = id + 25;
				else if(id <= 7)
					sid = id + 33;
				else if(id <= 15)
					sid = id-7;
				else if(id <= 23)
					sid = id+1;
				else if(id <= 31)
					sid = id-15;
				else if(id <= 39)
					sid = id-3;
				else
					sid = id+2;

				send_output(sid, (data & (1<<i)) != 0);
			}
}

WRITE8_MEMBER(wpc_out_device::out4_w)
{
	// This is gross, probably wrong, but also the best I could find.
	// Test case is No Good Gofers (ngg_13).
	out_w(space, first_after_led ? 5 : 4, data, mem_mask);
}

WRITE8_MEMBER(wpc_out_device::gi_w)
{
	gi_update();
	if((gi^data) & 0x80)
		send_output(41, data & 0x80 ? 1 : 0);
	gi = data;
}

WRITE8_MEMBER(wpc_out_device::led_w)
{
	first_after_led = true;
	machine().output().set_value("L:cpu led", data & 0x80 ? 1 : 0);
}

void wpc_out_device::device_start()
{
	save_item(NAME(state));
	save_item(NAME(gi));
	save_item(NAME(first_after_led));
	save_item(NAME(previous_gi_update));
	save_item(NAME(gi_time));

	timer = timer_alloc(0);
}

void wpc_out_device::device_reset()
{
	memset(state, 0x00, 6);
	first_after_led = false;
	gi = 0x00;
	previous_gi_update = attotime::zero;
	memset(gi_time, 0, sizeof(gi_time));
	timer->adjust(attotime::from_hz(10), 0, attotime::from_hz(10));
}

void wpc_out_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	gi_update();
	for(int i=0; i<gi_count; i++) {
		//      fprintf(stderr, "gi[%d] = %d\n", i, gi_time[i]);
		gi_time[i] = 0;
	}
}