summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mame/machine/pc9801_86.cpp188
-rw-r--r--src/mame/machine/pc9801_86.h28
2 files changed, 179 insertions, 37 deletions
diff --git a/src/mame/machine/pc9801_86.cpp b/src/mame/machine/pc9801_86.cpp
index 1416e01fd4b..3a5e2847b7e 100644
--- a/src/mame/machine/pc9801_86.cpp
+++ b/src/mame/machine/pc9801_86.cpp
@@ -9,15 +9,17 @@
TODO:
- joystick code should be shared between -26, -86 and -118
+ - Test all pcm modes
+ - Make volume work
+ - Recording
***************************************************************************/
#include "emu.h"
#include "machine/pc9801_86.h"
-#include "machine/pic8259.h"
-#include "sound/2608intf.h"
#define MAIN_CLOCK_X1 XTAL_1_9968MHz
+#define QUEUE_SIZE 32768
//**************************************************************************
// GLOBAL VARIABLES
@@ -37,21 +39,27 @@ READ8_MEMBER(pc9801_86_device::opn_porta_r)
WRITE8_MEMBER(pc9801_86_device::opn_portb_w){ m_joy_sel = data; }
-WRITE_LINE_MEMBER(pc9801_86_device::pc9801_sound_irq)
+WRITE_LINE_MEMBER(pc9801_86_device::sound_irq)
{
+ m_fmirq = state ? true : false;
/* TODO: seems to die very often */
- machine().device<pic8259_device>(":pic8259_slave")->ir4_w(state);
+ machine().device<pic8259_device>(":pic8259_slave")->ir4_w(state || (m_pcmirq ? ASSERT_LINE : CLEAR_LINE));
}
static MACHINE_CONFIG_FRAGMENT( pc9801_86_config )
- MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("opna", YM2608, MAIN_CLOCK_X1*4) // unknown clock / divider
- MCFG_YM2608_IRQ_HANDLER(WRITELINE(pc9801_86_device, pc9801_sound_irq))
+ MCFG_YM2608_IRQ_HANDLER(WRITELINE(pc9801_86_device, sound_irq))
MCFG_AY8910_PORT_A_READ_CB(READ8(pc9801_86_device, opn_porta_r))
//MCFG_AY8910_PORT_B_READ_CB(READ8(pc9801_state, opn_portb_r))
//MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(pc9801_state, opn_porta_w))
MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(pc9801_86_device, opn_portb_w))
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
+ MCFG_SOUND_ADD("dacl", DAC, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
+ MCFG_SOUND_ADD("dacr", DAC, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
MACHINE_CONFIG_END
//-------------------------------------------------
@@ -119,8 +127,10 @@ ioport_constructor pc9801_86_device::device_input_ports() const
pc9801_86_device::pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, PC9801_86, "pc9801_86", tag, owner, clock, "pc9801_86", __FILE__),
-// m_maincpu(*owner, "maincpu"),
- m_opna(*this, "opna")
+ m_opna(*this, "opna"),
+ m_dacl(*this, "dacl"),
+ m_dacr(*this, "dacr"),
+ m_queue(QUEUE_SIZE)
{
}
@@ -160,6 +170,7 @@ void pc9801_86_device::install_device(offs_t start, offs_t end, offs_t mask, off
void pc9801_86_device::device_start()
{
+ m_dac_timer = timer_alloc();
}
@@ -170,9 +181,15 @@ void pc9801_86_device::device_start()
void pc9801_86_device::device_reset()
{
UINT16 port_base = (ioport("OPNA_DSW")->read() & 1) << 8;
- install_device(port_base + 0x0088, port_base + 0x008f, 0, 0, read8_delegate(FUNC(pc9801_86_device::pc9801_86_r), this), write8_delegate(FUNC(pc9801_86_device::pc9801_86_w), this) );
-// install_device(0xa460, 0xa463, 0, 0, read8_delegate(FUNC(pc9801_86_device::pc9801_86_ext_r), this), write8_delegate(FUNC(pc9801_86_device::pc9801_86_ext_w), this) );
-
+ install_device(port_base + 0x0088, port_base + 0x008f, 0, 0, read8_delegate(FUNC(pc9801_86_device::opn_r), this), write8_delegate(FUNC(pc9801_86_device::opn_w), this) );
+ install_device(0xa460, 0xa463, 0, 0, read8_delegate(FUNC(pc9801_86_device::id_r), this), write8_delegate(FUNC(pc9801_86_device::mask_w), this));
+ install_device(0xa464, 0xa46f, 0, 0, read8_delegate(FUNC(pc9801_86_device::pcm_r), this), write8_delegate(FUNC(pc9801_86_device::pcm_w), this));
+ m_mask = 0;
+ m_head = m_tail = m_count = 0;
+ m_fmirq = m_pcmirq = false;
+ m_irq_rate = 0;
+ m_pcm_ctrl = m_pcm_mode = 0;
+ memset(&m_queue[0], 0, QUEUE_SIZE);
}
@@ -181,7 +198,7 @@ void pc9801_86_device::device_reset()
//**************************************************************************
-READ8_MEMBER(pc9801_86_device::pc9801_86_r)
+READ8_MEMBER(pc9801_86_device::opn_r)
{
if((offset & 1) == 0)
return m_opna->read(space, offset >> 1);
@@ -192,8 +209,7 @@ READ8_MEMBER(pc9801_86_device::pc9801_86_r)
}
}
-
-WRITE8_MEMBER(pc9801_86_device::pc9801_86_w)
+WRITE8_MEMBER(pc9801_86_device::opn_w)
{
if((offset & 1) == 0)
m_opna->write(space, offset >> 1,data);
@@ -201,27 +217,143 @@ WRITE8_MEMBER(pc9801_86_device::pc9801_86_w)
printf("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0x188,data);
}
-#if 0
-READ8_MEMBER( pc9801_86_device::pc9801_86_ext_r )
+READ8_MEMBER(pc9801_86_device::id_r)
+{
+ return 0x40 | m_mask;
+}
+
+WRITE8_MEMBER(pc9801_86_device::mask_w)
{
- if(offset == 0)
+ m_mask = data & 1;
+}
+
+READ8_MEMBER(pc9801_86_device::pcm_r)
+{
+ if((offset & 1) == 0)
{
- printf("OPNA EXT read ID [%02x]\n",offset);
- return 0xff;
+ switch(offset >> 1)
+ {
+ case 1:
+ return ((queue_count() == QUEUE_SIZE) ? 0x80 : 0) |
+ (!queue_count() ? 0x40 : 0);
+ case 2:
+ return m_pcm_ctrl | (m_pcmirq ? 0x10 : 0);
+ case 3:
+ return m_pcm_mode;
+ case 4:
+ return 0;
+ case 5:
+ return m_pcm_mute;
+ }
}
-
- printf("OPNA EXT read unk [%02x]\n",offset);
+ else // odd
+ printf("PC9801-86: Read to undefined port [%02x]\n",offset+0xa466);
return 0xff;
}
-WRITE8_MEMBER( pc9801_86_device::pc9801_86_ext_w )
+WRITE8_MEMBER(pc9801_86_device::pcm_w)
{
- if(offset == 0)
+ const int rates[] = {44100, 33075, 22050, 16538, 11025, 8268, 5513, 4134};
+ if((offset & 1) == 0)
{
- printf("OPNA EXT write mask %02x -> [%02x]\n",data,offset);
- return;
+ switch(offset >> 1)
+ {
+ case 1:
+ m_vol[data >> 5] = data & 0x0f;
+ break;
+ case 2:
+ m_pcm_ctrl = data & ~0x10;
+ if(data & 0x80)
+ m_dac_timer->adjust(attotime::from_hz(rates[data & 7]), 0, attotime::from_hz(rates[data & 7]));
+ else
+ m_dac_timer->adjust(attotime::never);
+ if(data & 8)
+ m_head = m_tail = m_count = 0;
+ if(!(data & 0x10))
+ {
+ m_pcmirq = false;
+ machine().device<pic8259_device>(":pic8259_slave")->ir4_w(m_fmirq ? ASSERT_LINE : CLEAR_LINE);
+ }
+ break;
+ case 3:
+ if(m_pcm_ctrl & 0x20)
+ m_irq_rate = (data + 1) * 128;
+ else
+ m_pcm_mode = data;
+ break;
+ case 4:
+ if(queue_count() < QUEUE_SIZE)
+ {
+ m_queue[m_head++] = data;
+ m_head %= QUEUE_SIZE;
+ m_count++;
+ }
+ break;
+ case 5:
+ m_pcm_mute = data;
+ break;
+ }
}
+ else // odd
+ printf("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0xa466,data);
+}
+
+int pc9801_86_device::queue_count()
+{
+ return m_count;
+}
- printf("OPNA EXT write unk %02x -> [%02x]\n",data,offset);
+UINT8 pc9801_86_device::queue_pop()
+{
+ if(!queue_count())
+ return 128;
+ UINT8 ret = m_queue[m_tail++];
+ m_tail %= QUEUE_SIZE;
+ m_count--;
+ return ret;
+}
+
+void pc9801_86_device::device_timer(emu_timer& timer, device_timer_id id, int param, void* ptr)
+{
+ INT16 lsample, rsample;
+
+ if((m_pcm_ctrl & 0x40) || !(m_pcm_ctrl & 0x80) || !queue_count())
+ return;
+
+ switch(m_pcm_mode & 0x70)
+ {
+ case 0x70: // 8bit stereo
+ m_dacl->write_signed8(queue_pop() + 128);
+ m_dacr->write_signed8(queue_pop() + 128);
+ break;
+ case 0x60: // 8bit left only
+ m_dacl->write_signed8(queue_pop() + 128);
+ break;
+ case 0x50: // 8bit right only
+ m_dacr->write_signed8(queue_pop() + 128);
+ break;
+ case 0x30: // 16bit stereo
+ lsample = queue_pop();
+ lsample |= queue_pop() << 8;
+ rsample = queue_pop();
+ rsample |= queue_pop() << 8;
+ m_dacl->write(lsample);
+ m_dacr->write(rsample);
+ break;
+ case 0x20: // 16bit left only
+ lsample = queue_pop();
+ lsample |= queue_pop() << 8;
+ m_dacl->write(lsample);
+ break;
+ case 0x10: // 16bit right only
+ rsample = queue_pop();
+ rsample |= queue_pop() << 8;
+ m_dacr->write(rsample);
+ break;
+ }
+ if((queue_count() < m_irq_rate) && (m_pcm_ctrl & 0x20))
+ {
+ m_pcmirq = true;
+ machine().device<pic8259_device>(":pic8259_slave")->ir4_w(ASSERT_LINE);
+ }
}
-#endif
diff --git a/src/mame/machine/pc9801_86.h b/src/mame/machine/pc9801_86.h
index f21eb50720b..61b48dcabb9 100644
--- a/src/mame/machine/pc9801_86.h
+++ b/src/mame/machine/pc9801_86.h
@@ -14,6 +14,7 @@
#include "machine/pic8259.h"
#include "sound/2608intf.h"
+#include "sound/dac.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -33,14 +34,13 @@ public:
DECLARE_READ8_MEMBER(opn_porta_r);
DECLARE_WRITE8_MEMBER(opn_portb_w);
- DECLARE_READ8_MEMBER(pc9801_86_r);
- DECLARE_WRITE8_MEMBER(pc9801_86_w);
- DECLARE_WRITE_LINE_MEMBER(pc9801_sound_irq);
-// DECLARE_READ8_MEMBER(pc9801_86_ext_r);
-// DECLARE_WRITE8_MEMBER(pc9801_86_ext_w);
-
-// required_device<cpu_device> m_maincpu;
- required_device<ym2608_device> m_opna;
+ DECLARE_READ8_MEMBER(opn_r);
+ DECLARE_WRITE8_MEMBER(opn_w);
+ DECLARE_READ8_MEMBER(id_r);
+ DECLARE_WRITE8_MEMBER(mask_w);
+ DECLARE_READ8_MEMBER(pcm_r);
+ DECLARE_WRITE8_MEMBER(pcm_w);
+ DECLARE_WRITE_LINE_MEMBER(sound_irq);
virtual const rom_entry *device_rom_region() const override;
protected:
// device-level overrides
@@ -48,10 +48,20 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
void install_device(offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_delegate rhandler, write8_delegate whandler);
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
- UINT8 m_joy_sel;
+ int queue_count();
+ UINT8 queue_pop();
+ UINT8 m_joy_sel, m_mask, m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
+ UINT16 m_head, m_tail, m_count, m_irq_rate;
+ bool m_pcmirq, m_fmirq;
+ required_device<ym2608_device> m_opna;
+ required_device<dac_device> m_dacl;
+ required_device<dac_device> m_dacr;
+ dynamic_buffer m_queue;
+ emu_timer *m_dac_timer;
};