/
cclimber.cpp
122 lines (89 loc) · 3.36 KB
/
cclimber.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria, hap
/***************************************************************************
Crazy Climber sound hardware
It has an AY-3-8910.
And 8KB ROM for voice samples, done with TTL chips.
***************************************************************************/
#include "emu.h"
#include "audio/cclimber.h"
#include "sound/ay8910.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(CCLIMBER_AUDIO, cclimber_audio_device, "cclimber_audio", "Crazy Climber Sound Board")
//-------------------------------------------------
// cclimber_audio_device: Constructor
//-------------------------------------------------
cclimber_audio_device::cclimber_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, CCLIMBER_AUDIO, tag, owner, clock),
m_dac(*this, "dac"),
m_volume(*this, "volume"),
m_rom(*this, "samples"),
m_sample_clockdiv(2)
{ }
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void cclimber_audio_device::device_start()
{
m_address = 0;
m_start_address = 0;
m_loop_address = 0;
m_sample_rate = 0;
m_sample_trigger = 0;
m_sample_timer = timer_alloc(FUNC(cclimber_audio_device::sample_tick), this);
m_sample_timer->adjust(attotime::zero);
// register for savestates
save_item(NAME(m_address));
save_item(NAME(m_start_address));
save_item(NAME(m_loop_address));
save_item(NAME(m_sample_rate));
save_item(NAME(m_sample_trigger));
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void cclimber_audio_device::device_add_mconfig(machine_config &config)
{
ay8910_device &aysnd(AY8910(config, "aysnd", DERIVED_CLOCK(1, 1)));
aysnd.port_a_write_callback().set(FUNC(cclimber_audio_device::start_address_w));
aysnd.port_b_write_callback().set(FUNC(cclimber_audio_device::loop_address_w));
aysnd.add_route(ALL_OUTPUTS, ":speaker", 0.5);
DAC_4BIT_R2R(config, m_dac).add_route(ALL_OUTPUTS, "volume", 0.5);
FILTER_VOLUME(config, m_volume).add_route(ALL_OUTPUTS, ":speaker", 1.0);
}
//-------------------------------------------------
// handlers
//-------------------------------------------------
void cclimber_audio_device::sample_rate_w(u8 data)
{
m_sample_rate = data;
}
void cclimber_audio_device::sample_volume_w(u8 data)
{
m_volume->flt_volume_set_volume(double(data & 0x1f) / 31.0); // range 0-31
}
void cclimber_audio_device::sample_trigger(int state)
{
// start playing on rising edge
if (state && !m_sample_trigger)
m_address = m_start_address * 64;
m_sample_trigger = state;
}
void cclimber_audio_device::sample_trigger_w(u8 data)
{
sample_trigger(data != 0);
}
TIMER_CALLBACK_MEMBER(cclimber_audio_device::sample_tick)
{
u16 mask = ((m_rom.bytes() << 1) - 1) & 0x3fff;
u8 data = m_rom[m_address >> 1 & mask];
// sample end marker, continue from loop point
if (data == 0x70)
m_address = m_loop_address * 64;
m_dac->write((m_address & 1) ? (data & 0xf) : (data >> 4));
if (m_sample_trigger)
m_address++;
m_sample_timer->adjust(attotime::from_ticks(256 - m_sample_rate, clock() / m_sample_clockdiv));
}