Added Sound Blaster 16, and proper 16 bit ISA DMA handling [Carl]

Added IBM VGA card [Carl]
This commit is contained in:
Miodrag Milanovic 2012-09-04 06:31:18 +00:00
parent b35677cdee
commit 40a39cedf1
11 changed files with 749 additions and 96 deletions

2
.gitattributes vendored
View File

@ -7342,6 +7342,8 @@ src/mess/video/isa_svga_s3.c svneol=native#text/plain
src/mess/video/isa_svga_s3.h svneol=native#text/plain
src/mess/video/isa_svga_tseng.c svneol=native#text/plain
src/mess/video/isa_svga_tseng.h svneol=native#text/plain
src/mess/video/isa_vga.c svneol=native#text/plain
src/mess/video/isa_vga.h svneol=native#text/plain
src/mess/video/k1ge.c svneol=native#text/plain
src/mess/video/k1ge.h svneol=native#text/plain
src/mess/video/kaypro.c svneol=native#text/plain

View File

@ -350,6 +350,7 @@ static SLOT_INTERFACE_START(pc_isa16_cards)
SLOT_INTERFACE("mda", ISA8_MDA)
SLOT_INTERFACE("cga", ISA8_CGA)
SLOT_INTERFACE("ega", ISA8_EGA)
SLOT_INTERFACE("vga", ISA8_VGA)
SLOT_INTERFACE("svga_et4k", ISA8_SVGA_ET4K)
SLOT_INTERFACE("svga_dm",ISA8_SVGA_CIRRUS)
SLOT_INTERFACE("com", ISA8_COM)
@ -373,6 +374,7 @@ static SLOT_INTERFACE_START(pc_isa16_cards)
SLOT_INTERFACE("ne2000", NE2000)
SLOT_INTERFACE("aha1542", AHA1542)
SLOT_INTERFACE("gus",ISA16_GUS)
SLOT_INTERFACE("sblaster_16", ISA16_SOUND_BLASTER_16)
SLOT_INTERFACE("svga_s3",ISA16_SVGA_S3)
SLOT_INTERFACE_END
@ -906,10 +908,10 @@ EVEN AMI 9203MGS 92F0626 EC32680 88 --> 33F8152
*/
ROM_START( i8555081 )
ROM_REGION(0x1000000,"maincpu", 0)
ROM_LOAD16_BYTE("33f8145.zm40", 0xe0000, 0x10000, CRC(0895894c) SHA1(7cee77828867ad1bdbe0ac223bc25d23c65b28a0))
ROM_RELOAD(0xfe0000, 0x10000)
ROM_LOAD16_BYTE("33f8146.zm41", 0xe0001, 0x10000, CRC(c6020680) SHA1(b25a64e4b2dca07c567648401100e04e89bbcddb))
ROM_LOAD16_BYTE("33f8145.zm40", 0xe0001, 0x10000, CRC(0895894c) SHA1(7cee77828867ad1bdbe0ac223bc25d23c65b28a0))
ROM_RELOAD(0xfe0001, 0x10000)
ROM_LOAD16_BYTE("33f8146.zm41", 0xe0000, 0x10000, CRC(c6020680) SHA1(b25a64e4b2dca07c567648401100e04e89bbcddb))
ROM_RELOAD(0xfe0000, 0x10000)
ROM_END
/*

View File

@ -26,6 +26,7 @@
#include "video/pc_cga.h"
#include "video/isa_cga.h"
#include "video/isa_ega.h"
#include "video/isa_vga.h"
#include "video/isa_svga_cirrus.h"
#include "video/isa_svga_s3.h"
#include "video/isa_svga_tseng.h"

View File

@ -182,7 +182,7 @@ WRITE8_MEMBER(at_state::pc_dma_write_byte)
READ8_MEMBER(at_state::pc_dma_read_word)
{
UINT16 result;
offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFF0000;
offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFE0000;
result = space.read_word(page_offset + ( offset << 1 ) );
m_dma_high_byte = result & 0xFF00;
@ -193,28 +193,27 @@ READ8_MEMBER(at_state::pc_dma_read_word)
WRITE8_MEMBER(at_state::pc_dma_write_word)
{
offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFF0000;
offs_t page_offset = (((offs_t) m_dma_offset[1][m_dma_channel & 3]) << 16) & 0xFE0000;
space.write_word(page_offset + ( offset << 1 ), m_dma_high_byte | data);
}
READ8_MEMBER( at_state::pc_dma8237_0_dack_r ) { return m_isabus->dack_r(0); }
READ8_MEMBER( at_state::pc_dma8237_1_dack_r ) { return m_isabus->dack_r(1); }
READ8_MEMBER( at_state::pc_dma8237_2_dack_r ) { return m_isabus->dack_r(2); }
READ8_MEMBER( at_state::pc_dma8237_3_dack_r ) { return m_isabus->dack_r(3); }
READ8_MEMBER( at_state::pc_dma8237_5_dack_r ) { return m_isabus->dack_r(5); }
READ8_MEMBER( at_state::pc_dma8237_6_dack_r ) { return m_isabus->dack_r(6); }
READ8_MEMBER( at_state::pc_dma8237_7_dack_r ) { return m_isabus->dack_r(7); }
READ8_MEMBER( at_state::pc_dma8237_5_dack_r ) { UINT16 ret = m_isabus->dack16_r(5); m_dma_high_byte = ret & 0xff00; return ret; }
READ8_MEMBER( at_state::pc_dma8237_6_dack_r ) { UINT16 ret = m_isabus->dack16_r(6); m_dma_high_byte = ret & 0xff00; return ret; }
READ8_MEMBER( at_state::pc_dma8237_7_dack_r ) { UINT16 ret = m_isabus->dack16_r(7); m_dma_high_byte = ret & 0xff00; return ret; }
WRITE8_MEMBER( at_state::pc_dma8237_0_dack_w ){ m_isabus->dack_w(0, data); }
WRITE8_MEMBER( at_state::pc_dma8237_1_dack_w ){ m_isabus->dack_w(1, data); }
WRITE8_MEMBER( at_state::pc_dma8237_2_dack_w ){ m_isabus->dack_w(2, data); }
WRITE8_MEMBER( at_state::pc_dma8237_3_dack_w ){ m_isabus->dack_w(3, data); }
WRITE8_MEMBER( at_state::pc_dma8237_5_dack_w ){ m_isabus->dack_w(5, data); }
WRITE8_MEMBER( at_state::pc_dma8237_6_dack_w ){ m_isabus->dack_w(6, data); }
WRITE8_MEMBER( at_state::pc_dma8237_7_dack_w ){ m_isabus->dack_w(7, data); }
WRITE8_MEMBER( at_state::pc_dma8237_5_dack_w ){ m_isabus->dack16_w(5, m_dma_high_byte | data); }
WRITE8_MEMBER( at_state::pc_dma8237_6_dack_w ){ m_isabus->dack16_w(6, m_dma_high_byte | data); }
WRITE8_MEMBER( at_state::pc_dma8237_7_dack_w ){ m_isabus->dack16_w(7, m_dma_high_byte | data); }
WRITE_LINE_MEMBER( at_state::at_dma8237_out_eop ) { m_isabus->eop_w(state == ASSERT_LINE ? 0 : 1 ); }

View File

@ -640,6 +640,19 @@ WRITE_LINE_MEMBER( isa16_device::drq5_w ) { m_out_drq5_func(state); }
WRITE_LINE_MEMBER( isa16_device::drq6_w ) { m_out_drq6_func(state); }
WRITE_LINE_MEMBER( isa16_device::drq7_w ) { m_out_drq7_func(state); }
UINT16 isa16_device::dack16_r(int line)
{
if (m_dma_device[line])
return dynamic_cast<device_isa16_card_interface *>(m_dma_device[line])->dack16_r(line);
return 0xffff;
}
void isa16_device::dack16_w(int line,UINT16 data)
{
if (m_dma_device[line])
return dynamic_cast<device_isa16_card_interface *>(m_dma_device[line])->dack16_w(line,data);
}
//-------------------------------------------------
// device_isa16_card_interface - constructor
//-------------------------------------------------
@ -662,3 +675,12 @@ void device_isa16_card_interface::set_isa_device()
{
m_isa = dynamic_cast<isa16_device *>(m_isa_dev);
}
UINT16 device_isa16_card_interface::dack16_r(int line)
{
return 0;
}
void device_isa16_card_interface::dack16_w(int line,UINT16 data)
{
}

View File

@ -178,7 +178,7 @@ public:
void nmi();
void set_nmi_state(bool enabled) { m_nmi_enabled = enabled; }
void set_dma_channel(UINT8 channel, device_isa8_card_interface *dev, bool do_eop);
virtual void set_dma_channel(UINT8 channel, device_isa8_card_interface *dev, bool do_eop);
protected:
void install_space(address_spacenum spacenum, device_t *dev, offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_device_func rhandler, const char* rhandler_name, write8_device_func whandler, const char *whandler_name);
void install_space(address_spacenum spacenum, offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_space_func rhandler, const char* rhandler_name, write8_space_func whandler, const char *whandler_name);
@ -307,6 +307,9 @@ public:
DECLARE_WRITE_LINE_MEMBER( drq6_w );
DECLARE_WRITE_LINE_MEMBER( drq7_w );
UINT16 dack16_r(int line);
void dack16_w(int line,UINT16 data);
protected:
// device-level overrides
virtual void device_start();
@ -340,6 +343,8 @@ public:
// construction/destruction
device_isa16_card_interface(const machine_config &mconfig, device_t &device);
virtual ~device_isa16_card_interface();
virtual UINT16 dack16_r(int line);
virtual void dack16_w(int line,UINT16 data);
void set_isa_device();
isa16_device *m_isa;

View File

@ -1,6 +1,6 @@
/***************************************************************************
ISA 8 bit Creative Labs Sound Blaster Sound Card
ISA 8/16 bit Creative Labs Sound Blaster Sound Card
TODO:
- implement DAC
@ -13,6 +13,7 @@
#include "isa_sblaster.h"
#include "sound/speaker.h"
#include "sound/3812intf.h"
#include "sound/262intf.h"
#include "sound/saa1099.h"
#include "sound/dac.h"
#include "machine/pic8259.h"
@ -35,6 +36,7 @@
jumperable? normally 0x220
*/
#define ym3812_StdClock XTAL_3_579545MHz
#define ymf262_StdClock XTAL_14_31818MHz
static INPUT_PORTS_START( sblaster )
PORT_START("pc_joy")
@ -51,7 +53,7 @@ static INPUT_PORTS_START( sblaster )
PORT_BIT(0xff,0x80,IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(1,0xff) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)
INPUT_PORTS_END
ioport_constructor sb8_device::device_input_ports() const
ioport_constructor sb_device::device_input_ports() const
{
return INPUT_PORTS_NAME( sblaster );
}
@ -59,22 +61,22 @@ ioport_constructor sb8_device::device_input_ports() const
static const int m_cmd_fifo_length[256] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x */
-1, -1, -1, -1, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, 2, 1, /* 0x */
2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, /* 1x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 2x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 3x */
2, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, /* 4x */
2, 3, 3, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, /* 4x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 5x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 6x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 7x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 8x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 9x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* Ax */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* Bx */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* Cx */
1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* Dx */
2, 1, 2, -1, 2, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* Ex */
-1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1 /* Fx */
4, -1, -1, -1, -1, -1, 4, -1, 4, -1, -1, -1, -1, -1, 4, -1, /* Bx */
4, -1, -1, -1, -1, -1, 4, -1, 4, -1, -1, -1, -1, -1, 4, -1, /* Cx */
1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, /* Dx */
2, 1, 2, 1, 2, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* Ex */
-1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1 /* Fx */
};
static const int protection_magic[4][9] =
@ -90,31 +92,57 @@ static const ym3812_interface pc_ym3812_interface =
NULL
};
static const ymf262_interface pc_ymf262_interface =
{
NULL
};
static MACHINE_CONFIG_FRAGMENT( sblaster1_0_config )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("ym3812", YM3812, ym3812_StdClock)
MCFG_SOUND_CONFIG(pc_ym3812_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 3.00)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 3.00)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 3.00)
MCFG_SOUND_ADD("saa1099.1", SAA1099, 4772720)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
MCFG_SOUND_ADD("saa1099.2", SAA1099, 4772720)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
MCFG_SOUND_ADD("sbdac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MCFG_SOUND_ADD("sbdacl", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
MCFG_SOUND_ADD("sbdacr", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
MACHINE_CONFIG_END
static MACHINE_CONFIG_FRAGMENT( sblaster1_5_config )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("ym3812", YM3812, ym3812_StdClock)
MCFG_SOUND_CONFIG(pc_ym3812_interface)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
/* no CM/S support (empty sockets) */
MCFG_SOUND_ADD("sbdac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MCFG_SOUND_ADD("sbdacl", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
MCFG_SOUND_ADD("sbdacr", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
MACHINE_CONFIG_END
static MACHINE_CONFIG_FRAGMENT( sblaster_16_config )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("ymf262", YMF262, ymf262_StdClock)
MCFG_SOUND_CONFIG(pc_ymf262_interface)
MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MCFG_SOUND_ADD("sbdacl", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
MCFG_SOUND_ADD("sbdacr", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
MACHINE_CONFIG_END
static READ8_DEVICE_HANDLER( ym3812_16_r )
{
@ -149,7 +177,7 @@ static WRITE8_DEVICE_HANDLER( saa1099_16_w )
}
}
void sb8_device::queue(UINT8 data)
void sb_device::queue(UINT8 data)
{
if (m_dsp.fifo_ptr < 15)
{
@ -164,11 +192,11 @@ void sb8_device::queue(UINT8 data)
}
}
void sb8_device::queue_r(UINT8 data)
void sb_device::queue_r(UINT8 data)
{
m_dsp.rbuf_status |= 0x80;
if (m_dsp.fifo_r_ptr < 15)
if (m_dsp.fifo_r_ptr < 52)
{
m_dsp.fifo_r[m_dsp.fifo_r_ptr] = data;
@ -181,16 +209,16 @@ void sb8_device::queue_r(UINT8 data)
}
}
UINT8 sb8_device::dequeue_r()
UINT8 sb_device::dequeue_r()
{
UINT8 data = m_dsp.fifo_r[0];
if (m_dsp.fifo_r_ptr > 0)
{
for (int i = 0; i < 15; i++)
for (int i = 0; i < 51; i++)
m_dsp.fifo_r[i] = m_dsp.fifo_r[i + 1];
m_dsp.fifo_r[15] = 0;
m_dsp.fifo_r[51] = 0;
m_dsp.fifo_r_ptr--;
}
@ -202,7 +230,7 @@ UINT8 sb8_device::dequeue_r()
}
READ8_MEMBER( sb8_device::dsp_reset_r )
READ8_MEMBER( sb_device::dsp_reset_r )
{
// printf("read DSP reset @ %x\n", offset);
if(offset)
@ -211,7 +239,7 @@ READ8_MEMBER( sb8_device::dsp_reset_r )
return 0xff;
}
WRITE8_MEMBER( sb8_device::dsp_reset_w )
WRITE8_MEMBER( sb_device::dsp_reset_w )
{
// printf("%02x to DSP reset @ %x\n", data, offset);
if(offset)
@ -231,9 +259,9 @@ WRITE8_MEMBER( sb8_device::dsp_reset_w )
}
m_dsp.reset_latch = data;
m_isa->drq1_w(0);
drq_w(0);
m_dsp.dma_autoinit = 0;
m_isa->irq5_w(0);
irq_w(0, IRQ_ALL);
m_timer->adjust(attotime::never, 0);
m_dsp.d_rptr = 0;
m_dsp.d_wptr = 0;
@ -243,7 +271,7 @@ WRITE8_MEMBER( sb8_device::dsp_reset_w )
//printf("%02x\n",data);
}
READ8_MEMBER( sb8_device::dsp_data_r )
READ8_MEMBER( sb_device::dsp_data_r )
{
// printf("read DSP data @ %x\n", offset);
if(offset)
@ -252,7 +280,7 @@ READ8_MEMBER( sb8_device::dsp_data_r )
return dequeue_r();
}
WRITE8_MEMBER( sb8_device::dsp_data_w )
WRITE8_MEMBER( sb_device::dsp_data_w )
{
// printf("%02x to DSP data @ %x\n", data, offset);
if(offset)
@ -260,20 +288,24 @@ WRITE8_MEMBER( sb8_device::dsp_data_w )
logerror("Soundblaster DSP data port undocumented write\n");
}
READ8_MEMBER(sb8_device::dsp_rbuf_status_r)
READ8_MEMBER(sb_device::dsp_rbuf_status_r)
{
// printf("read Rbufstat @ %x\n", offset);
if(offset)
{
if(m_dsp.version > 0x0400)
irq_w(0, IRQ_DMA16);
return 0xff;
}
// printf("Clear IRQ5\n");
m_isa->irq5_w(0); // reading this port ACKs the card's IRQ
irq_w(0, IRQ_DMA8); // reading this port ACKs the card's IRQ, 8-bit dma only?
return m_dsp.rbuf_status;
}
READ8_MEMBER(sb8_device::dsp_wbuf_status_r)
READ8_MEMBER(sb_device::dsp_wbuf_status_r)
{
// printf("read Wbufstat @ %x\n", offset);
if(offset)
@ -282,7 +314,7 @@ READ8_MEMBER(sb8_device::dsp_wbuf_status_r)
return m_dsp.wbuf_status;
}
WRITE8_MEMBER(sb8_device::dsp_rbuf_status_w)
WRITE8_MEMBER(sb_device::dsp_rbuf_status_w)
{
// printf("%02x to Rbufstat @ %x\n", data, offset);
if(offset)
@ -291,11 +323,12 @@ WRITE8_MEMBER(sb8_device::dsp_rbuf_status_w)
logerror("Soundblaster DSP Read Buffer status undocumented write\n");
}
void sb8_device::process_fifo(UINT8 cmd)
void sb_device::process_fifo(UINT8 cmd)
{
if (m_cmd_fifo_length[cmd] == -1)
{
printf("unemulated or undefined fifo command %02x\n",cmd);
logerror("SB: unemulated or undefined fifo command %02x\n",cmd);
m_dsp.fifo_ptr = 0;
}
else if(m_dsp.fifo_ptr == m_cmd_fifo_length[cmd])
{
@ -313,7 +346,8 @@ void sb8_device::process_fifo(UINT8 cmd)
m_dsp.dma_autoinit = 0;
m_dsp.dma_timer_started = false;
m_dsp.dma_throttled = false;
m_isa->drq1_w(1);
drq_w(1);
m_dsp.flags = 0;
break;
case 0x1c: // 8-bit DMA with autoinit
@ -322,7 +356,8 @@ void sb8_device::process_fifo(UINT8 cmd)
m_dsp.dma_autoinit = 1;
m_dsp.dma_timer_started = false;
m_dsp.dma_throttled = false;
m_isa->drq1_w(1);
drq_w(1);
m_dsp.flags = 0;
break;
case 0x40: // set time constant
@ -336,7 +371,7 @@ void sb8_device::process_fifo(UINT8 cmd)
case 0xd0: // halt 8-bit DMA
m_timer->adjust(attotime::never, 0);
m_isa->drq1_w(0); // drop DRQ
drq_w(0); // drop DRQ
m_dsp.dma_throttled = false;
m_dsp.dma_timer_started = false;
break;
@ -377,7 +412,7 @@ void sb8_device::process_fifo(UINT8 cmd)
m_dsp.prot_count++;
m_dack_out = (UINT8)(m_dsp.prot_value & 0xff);
m_isa->drq1_w(1);
drq_w(1);
break;
case 0xe4: // write test register
@ -389,20 +424,128 @@ void sb8_device::process_fifo(UINT8 cmd)
break;
case 0xf2: // send PIC irq
m_isa->irq5_w(1);
irq_w(1, IRQ_DMA8);
break;
case 0xf8: // ???
logerror("SB: Unknown command write 0xf8");
logerror("SB: Unknown command write 0xf8\n");
queue_r(0);
break;
default:
if(m_dsp.version >= 0x0201) // SB 2.0
{
switch(cmd)
{
case 0xda: // stop 8-bit autoinit
m_dsp.dma_autoinit = 0;
break;
}
}
if(m_dsp.version >= 0x0301) // SB Pro 2
{
switch(cmd)
{
case 0xe3: // copyright notice, check if in pro 2
const char* copyright = "NOT COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
int j = strlen(copyright);
for(int k = 4; k <= j; k++)
queue_r(copyright[k]);
break;
}
}
if(m_dsp.version >= 0x0400) // SB16
{
int mode;
switch(cmd)
{
case 0x0f: // read asp reg
queue_r(0);
case 0x0e: // write asp reg
case 0x02: // get asp version
case 0x04: // set asp mode register
case 0x05: // set asp codec param
logerror("SB16: unimplemented ASP command\n");
break;
case 0x41: // set output sample rate
m_dsp.frequency = m_dsp.fifo[2] + (m_dsp.fifo[1] << 8);
break;
case 0x42: // set input sample rate
m_dsp.adc_freq = m_dsp.fifo[2] + (m_dsp.fifo[1] << 8);
break;
case 0xd5: // pause 16-bit dma
m_timer->adjust(attotime::never, 0);
drq16_w(0); // drop DRQ
m_dsp.dma_throttled = false;
m_dsp.dma_timer_started = false;
break;
case 0xd6: // resume 16-bit dma
logerror("SB: 16-bit dma resume\n");
break;
case 0xd9: // stop 16-bit autoinit
m_dsp.dma_autoinit = 0;
break;
case 0xb0:
case 0xb6:
case 0xc0:
case 0xc6:
mode = m_dsp.fifo[1];
m_dsp.flags = 0;
m_dsp.dma_length = (m_dsp.fifo[2] + (m_dsp.fifo[3]<<8)) + 1;
if((cmd & 0xf0) == 0xb0)
{
m_dsp.flags |= SIXTEENBIT;
m_dsp.dma_length <<= 1;
drq16_w(1);
}
else
drq_w(1);
if(cmd & 0x04)
m_dsp.dma_autoinit = 1;
if(mode & 0x10)
m_dsp.flags |= SIGNED;
if(mode & 0x20)
{
m_dsp.flags |= STEREO;
m_dsp.dma_length <<= 1;
}
m_dsp.dma_transferred = 0;
m_dsp.dma_timer_started = false;
m_dsp.dma_throttled = false;
break;
case 0xb8:
case 0xbe:
case 0xc8:
case 0xce:
mode = m_dsp.fifo[1];
m_dsp.adc_length = (m_dsp.fifo[2] + (m_dsp.fifo[3]<<8)) + 1;
m_dsp.adc_transferred = 0;
if(cmd & 0x04)
m_dsp.dma_autoinit = 1;
if(mode & 0x20)
m_dsp.adc_length <<= 1;
if((cmd & 0xf0) == 0xb0)
{
m_dsp.adc_length <<= 1;
drq16_w(1);
}
else
drq_w(1);
logerror("SB: ADC capture unimplemented\n");
break;
case 0xf3: // send PIC irq
irq_w(1, IRQ_DMA16);
break;
case 0xfc:
queue_r((((m_dsp.flags & SIXTEENBIT) && m_dsp.dma_autoinit) << 4) | ((!(m_dsp.flags & SIXTEENBIT) && m_dsp.dma_autoinit) << 2));
break;
}
}
}
m_dsp.fifo_ptr = 0;
}
}
WRITE8_MEMBER(sb8_device::dsp_cmd_w)
WRITE8_MEMBER(sb_device::dsp_cmd_w)
{
// printf("%02x to DSP command @ %x\n", data, offset);
@ -415,7 +558,7 @@ WRITE8_MEMBER(sb8_device::dsp_cmd_w)
}
READ8_MEMBER ( sb8_device::joy_port_r )
READ8_MEMBER ( sb_device::joy_port_r )
{
UINT8 data = 0;
int delta;
@ -435,13 +578,93 @@ READ8_MEMBER ( sb8_device::joy_port_r )
return data;
}
WRITE8_MEMBER ( sb8_device::joy_port_w )
WRITE8_MEMBER ( sb_device::joy_port_w )
{
m_joy_time = machine().time();
}
READ8_MEMBER( sb16_device::mpu401_r )
{
UINT8 res;
irq_w(0, IRQ_MPU);
if(offset == 0) // data
{
if(m_head != m_tail)
{
res = m_mpu_queue[m_tail++];
m_tail %= 16;
}
else
res = 0xff;
}
else // status
{
res = ((m_head != m_tail)?0:0x80) | 0x3f; // bit 7 queue empty (DSR), bit 6 DRR (Data Receive Ready?)
}
return res;
}
WRITE8_MEMBER( sb16_device::mpu401_w )
{
if(offset == 0) // data
{
logerror("SB MPU401:%02x %02x\n",offset,data);
}
else // command
{
logerror("SB MPU401:%02x %02x\n",offset,data);
switch(data)
{
case 0xff: // reset
irq_w(1, IRQ_MPU);
m_head = m_tail = 0;
m_mpu_queue[m_head++] = 0xfe;
break;
}
}
}
READ8_MEMBER( sb_device::mixer_r )
{
if(offset == 0)
return m_mixer_index;
switch(m_mixer_index)
{
case 0: // reset
return 0;
default:
if(m_dsp.version >= 0x0400)
{
switch(m_mixer_index)
{
case 0x82: // irqs
return m_dsp.irq_active;
}
}
}
logerror("SB: Unimplemented read mixer command %02x\n", m_mixer_index);
return 0;
}
WRITE8_MEMBER( sb_device::mixer_w )
{
if(offset == 0)
{
m_mixer_index = data;
return;
}
switch(m_mixer_index)
{
case 0: // reset
return;
}
logerror("SB: Unimplemented write mixer command %02x\n", m_mixer_index);
return;
}
//**************************************************************************
// GLOBAL VARIABLES
@ -449,6 +672,7 @@ WRITE8_MEMBER ( sb8_device::joy_port_w )
const device_type ISA8_SOUND_BLASTER_1_0 = &device_creator<isa8_sblaster1_0_device>;
const device_type ISA8_SOUND_BLASTER_1_5 = &device_creator<isa8_sblaster1_5_device>;
const device_type ISA16_SOUND_BLASTER_16 = &device_creator<isa16_sblaster16_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
@ -465,17 +689,33 @@ machine_config_constructor isa8_sblaster1_5_device::device_mconfig_additions() c
return MACHINE_CONFIG_NAME( sblaster1_5_config );
}
machine_config_constructor isa16_sblaster16_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( sblaster_16_config );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
sb8_device::sb8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name) :
sb_device::sb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name) :
device_t(mconfig, type, name, tag, owner, clock),
device_isa8_card_interface(mconfig, *this),
m_dac(*this, "sbdac")
m_dacl(*this, "sbdacl"),
m_dacr(*this, "sbdacr")
{
}
sb8_device::sb8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name) :
sb_device(mconfig, type, tag, owner, clock, name),
device_isa8_card_interface(mconfig, *this)
{
}
sb16_device::sb16_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name) :
sb_device(mconfig, type, tag, owner, clock, name),
device_isa16_card_interface(mconfig, *this)
{
}
//-------------------------------------------------
// isa8_sblaster_device - constructor
@ -491,19 +731,34 @@ isa8_sblaster1_5_device::isa8_sblaster1_5_device(const machine_config &mconfig,
{
}
isa16_sblaster16_device::isa16_sblaster16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
sb16_device(mconfig, ISA16_SOUND_BLASTER_16, tag, owner, clock, "Sound Blaster 16")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void sb8_device::device_start()
{
m_isa->install_device( 0x0200, 0x0207, 0, 0, read8_delegate(FUNC(sb8_device::joy_port_r), this), write8_delegate(FUNC(sb8_device::joy_port_w), this));
m_isa->install_device( 0x0226, 0x0227, 0, 0, read8_delegate(FUNC(sb8_device::dsp_reset_r), this), write8_delegate(FUNC(sb8_device::dsp_reset_w), this));
m_isa->install_device(subdevice("ym3812"), 0x0228, 0x0229, 0, 0, FUNC(ym3812_16_r), FUNC(ym3812_16_w) );
m_isa->install_device( 0x022a, 0x022b, 0, 0, read8_delegate(FUNC(sb8_device::dsp_data_r), this), write8_delegate(FUNC(sb8_device::dsp_data_w), this) );
m_isa->install_device( 0x022c, 0x022d, 0, 0, read8_delegate(FUNC(sb8_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb8_device::dsp_cmd_w), this) );
m_isa->install_device( 0x022e, 0x022f, 0, 0, read8_delegate(FUNC(sb8_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb8_device::dsp_rbuf_status_w), this) );
m_isa->install_device(subdevice("ym3812"), 0x0388, 0x0389, 0, 0, FUNC(ym3812_16_r), FUNC(ym3812_16_w) );
m_isa->install_device( 0x0200, 0x0207, 0, 0, read8_delegate(FUNC(sb_device::joy_port_r), this), write8_delegate(FUNC(sb_device::joy_port_w), this));
m_isa->install_device( 0x0226, 0x0227, 0, 0, read8_delegate(FUNC(sb_device::dsp_reset_r), this), write8_delegate(FUNC(sb_device::dsp_reset_w), this));
m_isa->install_device( 0x022a, 0x022b, 0, 0, read8_delegate(FUNC(sb_device::dsp_data_r), this), write8_delegate(FUNC(sb_device::dsp_data_w), this) );
m_isa->install_device( 0x022c, 0x022d, 0, 0, read8_delegate(FUNC(sb_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_cmd_w), this) );
m_isa->install_device( 0x022e, 0x022f, 0, 0, read8_delegate(FUNC(sb_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_rbuf_status_w), this) );
if(m_dsp.version >= 0x0301)
{
m_isa->install_device(0x0224, 0x0225, 0, 0, read8_delegate(FUNC(sb_device::mixer_r), this), write8_delegate(FUNC(sb_device::mixer_w), this));
m_isa->install_device(subdevice("ymf262"), 0x0388, 0x038b, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
m_isa->install_device(subdevice("ymf262"), 0x0220, 0x0223, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
m_isa->install_device(subdevice("ymf262"), 0x0228, 0x0229, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
}
else
{
m_isa->install_device(subdevice("ym3812"), 0x0388, 0x0389, 0, 0, FUNC(ym3812_16_r), FUNC(ym3812_16_w) );
m_isa->install_device(subdevice("ym3812"), 0x0228, 0x0229, 0, 0, FUNC(ym3812_16_r), FUNC(ym3812_16_w) );
}
m_timer = timer_alloc(0, NULL);
}
@ -528,11 +783,38 @@ void isa8_sblaster1_5_device::device_start()
sb8_device::device_start();
}
void sb16_device::device_start()
{
m_isa->install_device( 0x0200, 0x0207, 0, 0, read8_delegate(FUNC(sb_device::joy_port_r), this), write8_delegate(FUNC(sb_device::joy_port_w), this));
m_isa->install_device( 0x0224, 0x0225, 0, 0, read8_delegate(FUNC(sb_device::mixer_r), this), write8_delegate(FUNC(sb_device::mixer_w), this));
m_isa->install_device( 0x0226, 0x0227, 0, 0, read8_delegate(FUNC(sb_device::dsp_reset_r), this), write8_delegate(FUNC(sb_device::dsp_reset_w), this));
m_isa->install_device( 0x022a, 0x022b, 0, 0, read8_delegate(FUNC(sb_device::dsp_data_r), this), write8_delegate(FUNC(sb_device::dsp_data_w), this) );
m_isa->install_device( 0x022c, 0x022d, 0, 0, read8_delegate(FUNC(sb_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_cmd_w), this) );
m_isa->install_device( 0x022e, 0x022f, 0, 0, read8_delegate(FUNC(sb_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_rbuf_status_w), this) );
m_isa->install_device( 0x0330, 0x0331, 0, 0, read8_delegate(FUNC(sb16_device::mpu401_r), this), write8_delegate(FUNC(sb16_device::mpu401_w), this));
m_isa->install_device(subdevice("ymf262"), 0x0388, 0x038b, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
m_isa->install_device(subdevice("ymf262"), 0x0220, 0x0223, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
m_isa->install_device(subdevice("ymf262"), 0x0228, 0x0229, 0, 0, FUNC(ymf262_r), FUNC(ymf262_w) );
m_head = 0;
m_tail = 0;
m_timer = timer_alloc(0, NULL);
}
void isa16_sblaster16_device::device_start()
{
set_isa_device();
m_isa->set_dma_channel(1, this, FALSE);
m_isa->set_dma_channel(5, this, FALSE);
m_dsp.version = 0x0405; // diagnose.exe rejects anything lower than 0x0402
sb16_device::device_start();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void sb8_device::device_reset()
void sb_device::device_reset()
{
m_dsp.prot_value = 0xaa;
m_dsp.prot_count = 0;
@ -541,17 +823,93 @@ void sb8_device::device_reset()
m_dsp.fifo_r_ptr = 0;
m_dsp.wbuf_status = 0;
m_dsp.rbuf_status = 0;
m_dsp.frequency = 22050; //?
m_dsp.irq_active = 0;
m_mixer_index = 0;
}
UINT8 sb8_device::dack_r(int line)
UINT8 sb_device::dack_r(int line)
{
// printf("dack_r: line %x out = %02x\n", line, m_dack_out);
m_isa->drq1_w(0); // drop DRQ?
m_dsp.adc_transferred++;
if(m_dsp.adc_transferred >= m_dsp.adc_length)
{
drq_w(0);
if (m_dsp.dma_autoinit)
{
m_dsp.adc_transferred = 0;
drq_w(1);
}
irq_w(1, IRQ_DMA8);
}
else
drq_w(1);
return m_dack_out;
}
UINT16 sb16_device::dack16_r(int line)
{
m_dsp.adc_transferred += 2;
if (m_dsp.adc_transferred >= m_dsp.adc_length)
{
drq16_w(0);
if (m_dsp.dma_autoinit)
{
m_dsp.adc_transferred = 0;
drq16_w(1);
}
irq_w(1, IRQ_DMA16);
}
else
drq16_w(1);
return m_dack_out;
}
void sb16_device::dack16_w(int line, UINT16 data)
{
// set the transfer timer on the 1st byte
if (!m_dsp.dma_timer_started)
{
m_timer->adjust(attotime::from_hz((double)m_dsp.frequency), 0, attotime::from_hz((double)m_dsp.frequency));
m_dsp.d_rptr = m_dsp.d_wptr = 0;
m_dsp.dma_timer_started = true;
}
m_dsp.data[m_dsp.d_wptr++] = data & 0xff;
m_dsp.data[m_dsp.d_wptr++] = data >> 8;
m_dsp.d_wptr %= 128;
if (m_dsp.d_wptr == m_dsp.d_rptr)
{
// printf("throttling DRQ\n");
drq16_w(0); // drop DRQ here
m_dsp.dma_throttled = true;
}
m_dsp.dma_transferred += 2;
if (m_dsp.dma_transferred >= m_dsp.dma_length)
{
// printf("DMA fill completed (%d out of %d)\n", m_dsp.dma_transferred, m_dsp.dma_length);
drq16_w(0); // drop DRQ here
if (m_dsp.dma_autoinit)
{
// printf("autoinit reset\n");
m_dsp.dma_transferred = 0;
if (!m_dsp.dma_throttled) // if we're not throttled, re-raise DRQ right now
{
drq16_w(1); // raise DRQ again (page 3-15 of the Creative manual indicates auto-init will keep going until you stop it)
}
}
irq_w(1, IRQ_DMA16); // raise IRQ as per the Creative manual
}
}
/* TODO: this mustn't be instant! */
void sb8_device::dack_w(int line, UINT8 data)
void sb_device::dack_w(int line, UINT8 data)
{
// printf("dack_w: line %x data %02x\n", line, data);
// if(data != 0x80)
@ -571,7 +929,7 @@ void sb8_device::dack_w(int line, UINT8 data)
if (m_dsp.d_wptr == m_dsp.d_rptr)
{
// printf("throttling DRQ\n");
m_isa->drq1_w(0); // drop DRQ here
drq_w(0); // drop DRQ here
m_dsp.dma_throttled = true;
}
@ -580,7 +938,7 @@ void sb8_device::dack_w(int line, UINT8 data)
{
// printf("DMA fill completed (%d out of %d)\n", m_dsp.dma_transferred, m_dsp.dma_length);
m_isa->drq1_w(0); // drop DRQ here
drq_w(0); // drop DRQ here
if (m_dsp.dma_autoinit)
{
@ -588,20 +946,81 @@ void sb8_device::dack_w(int line, UINT8 data)
m_dsp.dma_transferred = 0;
if (!m_dsp.dma_throttled) // if we're not throttled, re-raise DRQ right now
{
m_isa->drq1_w(1); // raise DRQ again (page 3-15 of the Creative manual indicates auto-init will keep going until you stop it)
drq_w(1); // raise DRQ again (page 3-15 of the Creative manual indicates auto-init will keep going until you stop it)
}
}
m_isa->irq5_w(1); // raise IRQ as per the Creative manual
irq_w(1, IRQ_DMA8); // raise IRQ as per the Creative manual
}
}
void sb8_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
void sb_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
{
// printf("DMA timer expire\n");
m_dac->write_unsigned8(m_dsp.data[m_dsp.d_rptr]);
m_dsp.data[m_dsp.d_rptr++] = 0x80;
UINT16 lsample, rsample;
switch (m_dsp.flags) {
case 0: // 8-bit unsigned mono
m_dacl->write_unsigned8(m_dsp.data[m_dsp.d_rptr]);
m_dacr->write_unsigned8(m_dsp.data[m_dsp.d_rptr]);
m_dsp.data[m_dsp.d_rptr++] = 0x80;
break;
case SIGNED: // 8-bit signed mono
m_dacl->write_unsigned8(m_dsp.data[m_dsp.d_rptr] + 128);
m_dacr->write_unsigned8(m_dsp.data[m_dsp.d_rptr] + 128);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
break;
case STEREO: // 8-bit unsigned stereo
m_dacl->write_unsigned8(m_dsp.data[m_dsp.d_rptr]);
m_dsp.data[m_dsp.d_rptr++] = 0x80;
m_dacr->write_unsigned8(m_dsp.data[m_dsp.d_rptr]);
m_dsp.data[m_dsp.d_rptr++] = 0x80;
break;
case SIGNED | STEREO: // 8-bit signed stereo
m_dacl->write_unsigned8(m_dsp.data[m_dsp.d_rptr] + 128);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dacr->write_unsigned8(m_dsp.data[m_dsp.d_rptr] + 128);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
break;
case SIXTEENBIT: // 16-bit unsigned mono
lsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x80;
m_dacl->write_unsigned16(lsample);
m_dacr->write_unsigned16(lsample);
break;
case SIXTEENBIT | SIGNED: // 16-bit signed mono
lsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dacl->write_unsigned16(lsample + 32768);
m_dacr->write_unsigned16(lsample + 32768);
break;
case SIXTEENBIT | STEREO: // 16-bit unsigned stereo
lsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x80;
m_dsp.d_rptr %= 128;
rsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x80;
m_dacl->write_unsigned16(lsample);
m_dacr->write_unsigned16(rsample);
break;
case SIXTEENBIT | SIGNED | STEREO: // 16-bit signed stereo
lsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.d_rptr %= 128;
rsample = m_dsp.data[m_dsp.d_rptr] | (m_dsp.data[m_dsp.d_rptr+1] << 8);
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dsp.data[m_dsp.d_rptr++] = 0x00;
m_dacl->write_unsigned16(lsample + 32768);
m_dacr->write_unsigned16(rsample + 32768);
break;
default: // ADPCM, ...?
logerror("SB: unimplemented sample type %x", m_dsp.flags);
}
m_dsp.d_rptr %= 128;
if (m_dsp.dma_throttled)
@ -609,7 +1028,10 @@ void sb8_device::device_timer(emu_timer &timer, device_timer_id tid, int param,
if (m_dsp.d_rptr == m_dsp.d_wptr)
{
// printf("unthrottling DRQ\n");
m_isa->drq1_w(1); // raise DRQ
if(m_dsp.flags & SIXTEENBIT) // 16-bit audio through 8-bit dma?
drq16_w(1);
else
drq_w(1); // raise DRQ
m_dsp.dma_throttled = false;
}
}

View File

@ -7,6 +7,16 @@
#include "machine/isa.h"
#include "sound/dac.h"
#define SIXTEENBIT 0x01
#define STEREO 0x02
#define ADPCM 0x04
#define SIGNED 0x08
#define IRQ_DMA8 0x01
#define IRQ_DMA16 0x02
#define IRQ_MPU 0x04
#define IRQ_ALL 0xff
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@ -17,31 +27,35 @@ struct sb8_dsp_state
UINT8 rbuf_status;
UINT8 wbuf_status;
UINT8 fifo[16],fifo_ptr;
UINT8 fifo_r[16],fifo_r_ptr;
UINT8 fifo_r[52],fifo_r_ptr;
UINT16 version;
UINT8 test_reg;
UINT8 speaker_on;
UINT32 prot_count;
INT32 prot_value;
UINT32 frequency;
UINT32 adc_freq;
UINT32 dma_length, dma_transferred;
UINT32 adc_length, adc_transferred;
UINT8 dma_autoinit;
UINT8 data[128], d_wptr, d_rptr;
bool dma_timer_started;
bool dma_throttled;
UINT8 flags;
UINT8 irq_active;
};
// ======================> sb8_device (parent)
class sb8_device :
public device_t,
public device_isa8_card_interface
class sb_device :
public device_t
{
public:
// construction/destruction
sb8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name);
sb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name);
required_device<dac_device> m_dac;
required_device<dac_device> m_dacl;
required_device<dac_device> m_dacr;
void process_fifo(UINT8 cmd);
void queue(UINT8 data);
@ -58,24 +72,42 @@ public:
DECLARE_WRITE8_MEMBER(dsp_cmd_w);
DECLARE_READ8_MEMBER(joy_port_r);
DECLARE_WRITE8_MEMBER(joy_port_w);
DECLARE_READ8_MEMBER(mixer_r);
DECLARE_WRITE8_MEMBER(mixer_w);
virtual ioport_constructor device_input_ports() const;
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual UINT8 dack_r(int line);
virtual void dack_w(int line, UINT8 data);
UINT8 dack_r(int line);
void dack_w(int line, UINT8 data);
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual void drq16_w(int state) { }
virtual void drq_w(int state) { }
virtual void irq_w(int state, int source) { }
struct sb8_dsp_state m_dsp;
UINT8 m_dack_out;
attotime m_joy_time;
UINT8 m_mixer_index;
private:
emu_timer *m_timer;
};
class sb8_device : public sb_device,
public device_isa8_card_interface
{
public:
// construction/destruction
sb8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name);
protected:
virtual void device_start();
virtual void drq_w(int state) { m_isa->drq1_w(state); }
virtual void irq_w(int state, int source) { m_isa->irq5_w(state); }
virtual UINT8 dack_r(int line) { return sb_device::dack_r(line); }
virtual void dack_w(int line, UINT8 data) { sb_device::dack_w(line, data); }
};
class isa8_sblaster1_0_device : public sb8_device
{
public:
@ -108,8 +140,48 @@ private:
// internal state
};
class sb16_device : public sb_device,
public device_isa16_card_interface
{
public:
// construction/destruction
sb16_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, const char *name);
DECLARE_READ8_MEMBER(mpu401_r);
DECLARE_WRITE8_MEMBER(mpu401_w);
protected:
virtual void device_start();
virtual UINT16 dack16_r(int line);
virtual UINT8 dack_r(int line) { return sb_device::dack_r(line); }
virtual void dack_w(int line, UINT8 data) { sb_device::dack_w(line, data); }
virtual void dack16_w(int line, UINT16 data);
virtual void drq16_w(int state) { m_isa->drq5_w(state); }
virtual void drq_w(int state) { m_isa->drq1_w(state); }
virtual void irq_w(int state, int source) { (state?m_dsp.irq_active|=source:m_dsp.irq_active&=~source); m_isa->irq5_w(m_dsp.irq_active&&1); }
private:
UINT8 m_mpu_queue[16];
UINT8 m_tail;
UINT8 m_head;
};
class isa16_sblaster16_device : public sb16_device
{
public:
// construction/destruction
isa16_sblaster16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
protected:
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { m_shortname = "isa_sblaster_16"; }
private:
// internal state
};
// device type definition
extern const device_type ISA8_SOUND_BLASTER_1_0;
extern const device_type ISA8_SOUND_BLASTER_1_5;
extern const device_type ISA16_SOUND_BLASTER_16;
#endif /* __ISA_SOUND_BLASTER_H__ */

View File

@ -137,7 +137,7 @@ SOUNDS += YM2612
SOUNDS += YM3812
SOUNDS += YM3526
#SOUNDS += Y8950
#SOUNDS += YMF262
SOUNDS += YMF262
#SOUNDS += YMF271
#SOUNDS += YMF278B
#SOUNDS += YMZ280B
@ -1449,6 +1449,7 @@ $(MESSOBJ)/pcshare.a: \
$(MESS_VIDEO)/isa_mda.o \
$(MESS_VIDEO)/crtc_ega.o \
$(MESS_VIDEO)/isa_ega.o \
$(MESS_VIDEO)/isa_vga.o \
$(MESS_VIDEO)/isa_svga_tseng.o \
$(MESS_VIDEO)/isa_svga_s3.o \
$(MESS_VIDEO)/isa_svga_cirrus.o \

91
src/mess/video/isa_vga.c Normal file
View File

@ -0,0 +1,91 @@
/***************************************************************************
ISA VGA wrapper
***************************************************************************/
#include "emu.h"
#include "isa_vga.h"
#include "video/pc_vga.h"
ROM_START( ibm_vga )
ROM_REGION(0x8000,"ibm_vga", 0)
ROM_LOAD("ibm-vga.bin", 0x00000, 0x8000, BAD_DUMP CRC(74e3fadb) SHA1(dce6491424f1726203776dfae9a967a98a4ba7b5) )
ROM_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type ISA8_VGA = &device_creator<isa8_vga_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor isa8_vga_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( pcvideo_vga_isa );
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const rom_entry *isa8_vga_device::device_rom_region() const
{
return ROM_NAME( ibm_vga );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// isa8_vga_device - constructor
//-------------------------------------------------
isa8_vga_device::isa8_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, ISA8_VGA, "IBM VGA Graphics Card", tag, owner, clock),
device_isa8_card_interface(mconfig, *this)
{
m_shortname = "ibm_vga";
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
static READ8_HANDLER( input_port_0_r ) { return 0xff; } //return space->machine().root_device().ioport("IN0")->read(); }
void isa8_vga_device::device_start()
{
set_isa_device();
video_start_vga( machine() );
pc_vga_init(machine(), input_port_0_r, NULL);
int i;
for (i = 0; i < 0x100; i++)
palette_set_color_rgb(machine(), i, 0, 0, 0);
pc_video_start(machine());
m_isa->install_rom(this, 0xc0000, 0xc7fff, 0, 0, "ibm_vga", "ibm_vga");
m_isa->install_device(0x3b0, 0x3bf, 0, 0, FUNC(vga_port_03b0_r), FUNC(vga_port_03b0_w));
m_isa->install_device(0x3c0, 0x3cf, 0, 0, FUNC(vga_port_03c0_r), FUNC(vga_port_03c0_w));
m_isa->install_device(0x3d0, 0x3df, 0, 0, FUNC(vga_port_03d0_r), FUNC(vga_port_03d0_w));
m_isa->install_memory(0xa0000, 0xbffff, 0, 0, FUNC(vga_mem_r), FUNC(vga_mem_w));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void isa8_vga_device::device_reset()
{
pc_vga_reset(machine());
}

36
src/mess/video/isa_vga.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#ifndef __ISA_VGA_H__
#define __ISA_VGA_H__
#include "emu.h"
#include "machine/isa.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> isa8_vga_device
class isa8_vga_device :
public device_t,
public device_isa8_card_interface
{
public:
// construction/destruction
isa8_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
virtual const rom_entry *device_rom_region() const;
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
};
// device type definition
extern const device_type ISA8_VGA;
#endif /* __ISA_VGA_H__ */