1 // license:BSD-3-Clause
2 // copyright-holders:Chris Hardy
3 #include "emu.h"
4 #include "sound/sn76496.h"
5 #include "sound/msm5205.h"
6 #include "includes/trackfld.h"
7 #include "audio/trackfld.h"
8 
9 
10 #define TIMER_RATE (4096/4)
11 
12 
13 
14 DEFINE_DEVICE_TYPE(TRACKFLD_AUDIO, trackfld_audio_device, "trackfld_audio", "Track And Field Audio")
15 
trackfld_audio_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)16 trackfld_audio_device::trackfld_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
17 	: device_t(mconfig, TRACKFLD_AUDIO, tag, owner, clock)
18 	, m_audiocpu(*this, finder_base::DUMMY_TAG)
19 	, m_vlm(*this, finder_base::DUMMY_TAG)
20 	, m_last_addr(0)
21 	, m_last_irq(0)
22 {
23 }
24 
25 //-------------------------------------------------
26 //  device_start - device-specific startup
27 //-------------------------------------------------
28 
device_start()29 void trackfld_audio_device::device_start()
30 {
31 	/* sound */
32 	save_item(NAME(m_last_addr));
33 	save_item(NAME(m_last_irq));
34 }
35 
36 //-------------------------------------------------
37 //  device_reset - device-specific reset
38 //-------------------------------------------------
39 
device_reset()40 void trackfld_audio_device::device_reset()
41 {
42 	m_last_addr = 0;
43 	m_last_irq = 0;
44 }
45 
46 /* The timer port on TnF and HyperSports sound hardware is derived from
47    a 14.318 MHz clock crystal which is passed  through a couple of 74ls393
48     ripple counters.
49     Various outputs of the ripper counters clock the various chips.
50     The Z80 uses 14.318 MHz / 4 (3.4MHz)
51     The SN chip uses 14.318 MHz / 8 (1.7MHz)
52     And the timer is connected to 14.318 MHz / 4096
53     As we are using the Z80 clockrate as a base value we need to multiply
54     the no of cycles by 4 to undo the 14.318/4 operation
55 */
56 
trackfld_sh_timer_r()57 uint8_t trackfld_audio_device::trackfld_sh_timer_r()
58 {
59 	uint32_t clock = m_audiocpu->total_cycles() / TIMER_RATE;
60 
61 	return clock & 0xF;
62 }
63 
trackfld_speech_r()64 uint8_t trackfld_audio_device::trackfld_speech_r()
65 {
66 	return m_vlm->bsy() ? 0x10 : 0;
67 }
68 
trackfld_sound_w(offs_t offset,uint8_t data)69 void trackfld_audio_device::trackfld_sound_w(offs_t offset, uint8_t data)
70 {
71 	int changes = offset ^ m_last_addr;
72 
73 	/* A7 = data enable for VLM5030 (don't care )          */
74 	/* A8 = STA pin (1->0 data data  , 0->1 start speech   */
75 	/* A9 = RST pin 1=reset                                */
76 
77 	/* A8 VLM5030 ST pin */
78 	if (changes & 0x100)
79 		m_vlm->st(offset & 0x100);
80 
81 	/* A9 VLM5030 RST pin */
82 	if (changes & 0x200)
83 		m_vlm->rst(offset & 0x200);
84 
85 	m_last_addr = offset;
86 }
87 
hyperspt_sh_timer_r()88 uint8_t trackfld_audio_device::hyperspt_sh_timer_r()
89 {
90 	uint32_t clock = m_audiocpu->total_cycles() / TIMER_RATE;
91 
92 	if (m_vlm != nullptr)
93 		return (clock & 0x3) | (m_vlm->bsy() ? 0x04 : 0);
94 	else
95 		return (clock & 0x3);
96 }
97 
hyperspt_sound_w(offs_t offset,uint8_t data)98 void trackfld_audio_device::hyperspt_sound_w(offs_t offset, uint8_t data)
99 {
100 	int changes = offset ^ m_last_addr;
101 
102 	/* A3 = data enable for VLM5030 (don't care )          */
103 	/* A4 = STA pin (1->0 data data  , 0->1 start speech   */
104 	/* A5 = RST pin 1=reset                                */
105 	/* A6 = VLM5030    output disable (don't care ) */
106 	/* A7 = kONAMI DAC output disable (don't care ) */
107 	/* A8 = SN76489    output disable (don't care ) */
108 
109 	/* A4 VLM5030 ST pin */
110 	if (changes & 0x10)
111 		m_vlm->st(offset & 0x10);
112 
113 	/* A5 VLM5030 RST pin */
114 	if( changes & 0x20 )
115 		m_vlm->rst(offset & 0x20);
116 
117 	m_last_addr = offset;
118 }
119 
120 
121 
WRITE_LINE_MEMBER(trackfld_audio_device::sh_irqtrigger_w)122 WRITE_LINE_MEMBER(trackfld_audio_device::sh_irqtrigger_w)
123 {
124 	if (m_last_irq == 0 && state)
125 	{
126 		/* setting bit 0 low then high triggers IRQ on the sound CPU */
127 		m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); // Z80
128 	}
129 
130 	m_last_irq = state;
131 }
132