mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
mu80: Add the fixed interrupt
swp20: Add some more identified registers
This commit is contained in:
parent
d1cd540e7d
commit
b72de1cf6e
@ -29,8 +29,8 @@ void swp20_device::device_reset()
|
||||
m_waverom_access = 0;
|
||||
m_waverom_val = 0;
|
||||
|
||||
m_p3c_port = 0x00;
|
||||
m_p3c_address = true;
|
||||
m_eq_port = 0x00;
|
||||
m_eq_address = true;
|
||||
m_voice = 0x00;
|
||||
m_keyon = 0;
|
||||
m_keyoff = 0;
|
||||
@ -42,6 +42,19 @@ void swp20_device::map(address_map &map)
|
||||
|
||||
map(0x01, 0x01).w(FUNC(swp20_device::voice_w));
|
||||
|
||||
map(0x10, 0x10).rw(FUNC(swp20_device::pitch_r<1>), FUNC(swp20_device::pitch_w<1>));
|
||||
map(0x11, 0x11).rw(FUNC(swp20_device::pitch_r<0>), FUNC(swp20_device::pitch_w<0>));
|
||||
|
||||
map(0x14, 0x14).rw(FUNC(swp20_device::pan_l_r), FUNC(swp20_device::pan_l_w));
|
||||
map(0x15, 0x15).rw(FUNC(swp20_device::pan_r_r), FUNC(swp20_device::pan_r_w));
|
||||
|
||||
map(0x26, 0x26).rw(FUNC(swp20_device::sample_start_r<2>), FUNC(swp20_device::sample_start_w<2>));
|
||||
map(0x27, 0x27).rw(FUNC(swp20_device::sample_start_r<1>), FUNC(swp20_device::sample_start_w<1>));
|
||||
map(0x28, 0x28).rw(FUNC(swp20_device::sample_start_r<0>), FUNC(swp20_device::sample_start_w<0>));
|
||||
map(0x29, 0x29).rw(FUNC(swp20_device::sample_format_r), FUNC(swp20_device::sample_format_w));
|
||||
map(0x2a, 0x2a).rw(FUNC(swp20_device::sample_end_r<1>), FUNC(swp20_device::sample_end_w<1>));
|
||||
map(0x2b, 0x2b).rw(FUNC(swp20_device::sample_end_r<0>), FUNC(swp20_device::sample_end_w<0>));
|
||||
map(0x2c, 0x2c).rw(FUNC(swp20_device::sample_address_r<3>), FUNC(swp20_device::sample_address_w<3>));
|
||||
map(0x2d, 0x2d).rw(FUNC(swp20_device::sample_address_r<2>), FUNC(swp20_device::sample_address_w<2>));
|
||||
map(0x2e, 0x2e).rw(FUNC(swp20_device::sample_address_r<1>), FUNC(swp20_device::sample_address_w<1>));
|
||||
map(0x2f, 0x2f).rw(FUNC(swp20_device::sample_address_r<0>), FUNC(swp20_device::sample_address_w<0>));
|
||||
@ -50,23 +63,15 @@ void swp20_device::map(address_map &map)
|
||||
map(0x3a, 0x3a).r(FUNC(swp20_device::waverom_val_r<1>));
|
||||
map(0x3b, 0x3b).r(FUNC(swp20_device::waverom_val_r<0>));
|
||||
|
||||
map(0x3c, 0x3c).w(FUNC(swp20_device::p3c_w));
|
||||
map(0x3c, 0x3c).w(FUNC(swp20_device::eq_w));
|
||||
}
|
||||
|
||||
// init mu80:
|
||||
// 48394: <- 47aea
|
||||
// write 04.7f 00.14 01.90 to +3c
|
||||
// write 01.90 80-ff, 473ea++
|
||||
// write 01.94 80-ff, 4746a++
|
||||
// write 01.98 80-ff, 474ea++
|
||||
// write 01.9c 80-ff, 4756a++
|
||||
|
||||
// write 01.a0
|
||||
// write 40-5f.data
|
||||
// etc
|
||||
|
||||
void swp20_device::voice_w(u8 data)
|
||||
{
|
||||
// Code uses 20-3f for voices on the second swp, it looks like
|
||||
// just leaking internal information and the top bits are not
|
||||
// significant
|
||||
|
||||
m_voice = data & 0x1f;
|
||||
}
|
||||
|
||||
@ -80,7 +85,79 @@ template<int sel> u8 swp20_device::waverom_val_r()
|
||||
return read_word(m_sample_address[0x1f]*2) >> (8*sel);
|
||||
}
|
||||
|
||||
template<int sel> void swp20_device::sample_address_w(offs_t offset, u8 data)
|
||||
void swp20_device::pan_l_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
m_pan_l[m_voice] = data;
|
||||
}
|
||||
|
||||
u8 swp20_device::pan_l_r()
|
||||
{
|
||||
return m_pan_l[m_voice];
|
||||
}
|
||||
|
||||
void swp20_device::pan_r_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
m_pan_r[m_voice] = data;
|
||||
}
|
||||
|
||||
u8 swp20_device::pan_r_r()
|
||||
{
|
||||
return m_pan_r[m_voice];
|
||||
}
|
||||
|
||||
template<int sel> void swp20_device::pitch_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
m_pitch[m_voice] = (m_pitch[m_voice] & ~(0xff << (8*sel))) | (data << (8*sel));
|
||||
}
|
||||
|
||||
template<int sel> u8 swp20_device::pitch_r()
|
||||
{
|
||||
return m_pitch[m_voice] >> (8*sel);
|
||||
}
|
||||
template<int sel> void swp20_device::sample_start_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
m_sample_start[m_voice] = (m_sample_start[m_voice] & ~(0xff << (8*sel))) | (data << (8*sel));
|
||||
// if(!sel)
|
||||
// logerror("sample_start[%02x] = %04x\n", m_voice, m_sample_start[m_voice]);
|
||||
}
|
||||
|
||||
template<int sel> u8 swp20_device::sample_start_r()
|
||||
{
|
||||
return m_sample_start[m_voice] >> (8*sel);
|
||||
}
|
||||
|
||||
template<int sel> void swp20_device::sample_end_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
m_sample_end[m_voice] = (m_sample_end[m_voice] & ~(0xff << (8*sel))) | (data << (8*sel));
|
||||
// if(!sel)
|
||||
// logerror("sample_end[%02x] = %04x\n", m_voice, m_sample_end[m_voice]);
|
||||
}
|
||||
|
||||
template<int sel> u8 swp20_device::sample_end_r()
|
||||
{
|
||||
return m_sample_end[m_voice] >> (8*sel);
|
||||
}
|
||||
|
||||
void swp20_device::sample_format_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
m_sample_format[m_voice] = data;
|
||||
}
|
||||
|
||||
u8 swp20_device::sample_format_r()
|
||||
{
|
||||
return m_sample_format[m_voice];
|
||||
}
|
||||
|
||||
template<int sel> void swp20_device::sample_address_w(u8 data)
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
@ -89,27 +166,31 @@ template<int sel> void swp20_device::sample_address_w(offs_t offset, u8 data)
|
||||
logerror("sample_address[%02x] = %04x\n", m_voice, m_sample_address[m_voice]);
|
||||
}
|
||||
|
||||
template<int sel> u8 swp20_device::sample_address_r(offs_t offset)
|
||||
template<int sel> u8 swp20_device::sample_address_r()
|
||||
{
|
||||
return m_sample_address[m_voice] >> (8*sel);
|
||||
}
|
||||
|
||||
void swp20_device::p3c_w(u8 data)
|
||||
void swp20_device::eq_w(u8 data)
|
||||
{
|
||||
if(m_p3c_address)
|
||||
m_p3c_port = data;
|
||||
else
|
||||
logerror("p3c %02x = %02x\n", m_p3c_port, data);
|
||||
if(m_eq_address)
|
||||
m_eq_port = data;
|
||||
else {
|
||||
if(0)
|
||||
logerror("eq %02x = %02x\n", m_eq_port, data);
|
||||
}
|
||||
|
||||
m_p3c_address = !m_p3c_address;
|
||||
m_eq_address = !m_eq_address;
|
||||
}
|
||||
|
||||
u8 swp20_device::snd_r(offs_t offset)
|
||||
{
|
||||
logerror("r %02x %s\n", offset, machine().describe_context());
|
||||
// logerror("r %02x %s\n", offset, machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 rr[0x20*0x40];
|
||||
|
||||
void swp20_device::snd_w(offs_t offset, u8 data)
|
||||
{
|
||||
// Registers 0-f are global, 10-3f per-voice
|
||||
@ -129,8 +210,13 @@ void swp20_device::snd_w(offs_t offset, u8 data)
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
logerror("w %02x.%02x, %02x %s\n", m_voice, offset, data, machine().describe_context());
|
||||
default: {
|
||||
if(data != rr[m_voice * 0x40 + offset]) {
|
||||
rr[m_voice * 0x40 + offset] = data;
|
||||
if(offset != 0x34)
|
||||
logerror("w %02x.%02x, %02x %s\n", m_voice, offset, data, machine().describe_context());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,26 +25,45 @@ protected:
|
||||
private:
|
||||
sound_stream *m_stream;
|
||||
|
||||
std::array<u8, 0x20> m_pan_l;
|
||||
std::array<u8, 0x20> m_pan_r;
|
||||
std::array<u16, 0x20> m_pitch;
|
||||
std::array<u32, 0x20> m_sample_start;
|
||||
std::array<u16, 0x20> m_sample_end;
|
||||
std::array<u8, 0x20> m_sample_format;
|
||||
std::array<u32, 0x20> m_sample_address;
|
||||
|
||||
u16 m_waverom_val;
|
||||
u8 m_waverom_access;
|
||||
|
||||
u8 m_p3c_port;
|
||||
bool m_p3c_address;
|
||||
u8 m_eq_port;
|
||||
bool m_eq_address;
|
||||
u8 m_voice;
|
||||
u32 m_keyon;
|
||||
u32 m_keyoff;
|
||||
|
||||
void voice_w(u8 data);
|
||||
template<int sel> void sample_address_w(offs_t offset, u8 data);
|
||||
template<int sel> u8 sample_address_r(offs_t offset);
|
||||
|
||||
void pan_l_w(u8 data);
|
||||
u8 pan_l_r();
|
||||
void pan_r_w(u8 data);
|
||||
u8 pan_r_r();
|
||||
template<int sel> void pitch_w(u8 data);
|
||||
template<int sel> u8 pitch_r();
|
||||
template<int sel> void sample_start_w(u8 data);
|
||||
template<int sel> u8 sample_start_r();
|
||||
template<int sel> void sample_end_w(u8 data);
|
||||
template<int sel> u8 sample_end_r();
|
||||
void sample_format_w(u8 data);
|
||||
u8 sample_format_r();
|
||||
template<int sel> void sample_address_w(u8 data);
|
||||
template<int sel> u8 sample_address_r();
|
||||
|
||||
void waverom_access_w(u8 data);
|
||||
template<int sel> u8 waverom_val_r();
|
||||
|
||||
// Generic upload port
|
||||
void p3c_w(u8 data);
|
||||
// Generic upload port, connected to the EQ on the first swp20
|
||||
void eq_w(u8 data);
|
||||
|
||||
// Generic catch-all
|
||||
u8 snd_r(offs_t offset);
|
||||
|
@ -2,11 +2,17 @@
|
||||
// copyright-holders:R. Belmont, Olivier Galibert
|
||||
/*************************************************************************************
|
||||
|
||||
Yamaha MU-80 and MU-100 : 32-voice polyphonic/multitimbral General MIDI/GS/XG tone modules
|
||||
Yamaha MU-80 : 32-part, 64-note polyphonic/multitimbral General MIDI/GS/XG
|
||||
tone module
|
||||
Preliminary driver by R. Belmont and O. Galibert
|
||||
|
||||
The first XG-capable module (mu15 and mu50 came out later). Uses a distributed
|
||||
structure of chips, with two chained SWP20 providing 32-notes each with a MEG
|
||||
effects processor at the end of the chain followed by an EQ chip on the result.
|
||||
|
||||
MU80 CPU: Hitachi H8/3002 (HD6413D02F16), strapped for mode 4, with a 12 MHz oscillator
|
||||
Sound ASICs: 2x Yamaha YMM275-F/SWP20 + 2x YMM279-F/SWD wave decoders + HD62908 "MEG" effects processor
|
||||
Sound ASICs: 2x Yamaha YMM275-F/SWP20 + 2x YMM279-F/SWD wave decoders + HD62908 "MEG"
|
||||
effects processor
|
||||
|
||||
I/O ports from service manual:
|
||||
|
||||
@ -213,6 +219,7 @@ private:
|
||||
u16 pb_r();
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
void mu80_map(address_map &map);
|
||||
};
|
||||
|
||||
@ -221,6 +228,12 @@ void mu80_state::machine_start()
|
||||
cur_p6 = cur_pa = cur_pb = cur_ic32 = 0xff;
|
||||
}
|
||||
|
||||
void mu80_state::machine_reset()
|
||||
{
|
||||
// Active-low, wired to gnd
|
||||
m_mu80cpu->set_input_line(0, ASSERT_LINE);
|
||||
}
|
||||
|
||||
void mu80_state::mu80_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x07ffff).rom().region("mu80cpu", 0);
|
||||
|
Loading…
Reference in New Issue
Block a user