|
|
|
@ -54,16 +54,18 @@ static struct { |
|
|
|
} conf = {0x240, 7, 3, 44100}; |
|
|
|
|
|
|
|
typedef struct GUSState { |
|
|
|
ISADevice dev; |
|
|
|
GUSEmuState emu; |
|
|
|
QEMUSoundCard card; |
|
|
|
int freq; |
|
|
|
uint32_t freq; |
|
|
|
uint32_t port; |
|
|
|
int pos, left, shift, irqs; |
|
|
|
GUSsample *mixbuf; |
|
|
|
uint8_t himem[1024 * 1024 + 32 + 4096]; |
|
|
|
int samples; |
|
|
|
SWVoiceOut *voice; |
|
|
|
int64_t last_ticks; |
|
|
|
qemu_irq *pic; |
|
|
|
qemu_irq pic; |
|
|
|
} GUSState; |
|
|
|
|
|
|
|
IO_READ_PROTO (gus_readb) |
|
|
|
@ -168,8 +170,8 @@ reset: |
|
|
|
int GUS_irqrequest (GUSEmuState *emu, int hwirq, int n) |
|
|
|
{ |
|
|
|
GUSState *s = emu->opaque; |
|
|
|
/* qemu_irq_lower (s->pic[hwirq]); */ |
|
|
|
qemu_irq_raise (s->pic[hwirq]); |
|
|
|
/* qemu_irq_lower (s->pic); */ |
|
|
|
qemu_irq_raise (s->pic); |
|
|
|
s->irqs += n; |
|
|
|
ldebug ("irqrequest %d %d %d\n", hwirq, n, s->irqs); |
|
|
|
return n; |
|
|
|
@ -179,7 +181,7 @@ void GUS_irqclear (GUSEmuState *emu, int hwirq) |
|
|
|
{ |
|
|
|
GUSState *s = emu->opaque; |
|
|
|
ldebug ("irqclear %d %d\n", hwirq, s->irqs); |
|
|
|
qemu_irq_lower (s->pic[hwirq]); |
|
|
|
qemu_irq_lower (s->pic); |
|
|
|
s->irqs -= 1; |
|
|
|
#ifdef IRQ_STORM |
|
|
|
if (s->irqs > 0) { |
|
|
|
@ -250,16 +252,14 @@ static int GUS_load (QEMUFile *f, void *opaque, int version_id) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int GUS_init (qemu_irq *pic) |
|
|
|
static int gus_initfn (ISADevice *dev) |
|
|
|
{ |
|
|
|
GUSState *s; |
|
|
|
GUSState *s = DO_UPCAST(GUSState, dev, dev); |
|
|
|
struct audsettings as; |
|
|
|
|
|
|
|
s = qemu_mallocz (sizeof (*s)); |
|
|
|
|
|
|
|
AUD_register_card ("gus", &s->card); |
|
|
|
|
|
|
|
as.freq = conf.freq; |
|
|
|
as.freq = s->freq; |
|
|
|
as.nchannels = 2; |
|
|
|
as.fmt = AUD_FMT_S16; |
|
|
|
as.endianness = GUS_ENDIANNESS; |
|
|
|
@ -283,34 +283,57 @@ int GUS_init (qemu_irq *pic) |
|
|
|
s->samples = AUD_get_buffer_size_out (s->voice) >> s->shift; |
|
|
|
s->mixbuf = qemu_mallocz (s->samples << s->shift); |
|
|
|
|
|
|
|
register_ioport_write (conf.port, 1, 1, gus_writeb, s); |
|
|
|
register_ioport_write (conf.port, 1, 2, gus_writew, s); |
|
|
|
register_ioport_write (s->port, 1, 1, gus_writeb, s); |
|
|
|
register_ioport_write (s->port, 1, 2, gus_writew, s); |
|
|
|
|
|
|
|
register_ioport_read ((conf.port + 0x100) & 0xf00, 1, 1, gus_readb, s); |
|
|
|
register_ioport_read ((conf.port + 0x100) & 0xf00, 1, 2, gus_readw, s); |
|
|
|
register_ioport_read ((s->port + 0x100) & 0xf00, 1, 1, gus_readb, s); |
|
|
|
register_ioport_read ((s->port + 0x100) & 0xf00, 1, 2, gus_readw, s); |
|
|
|
|
|
|
|
register_ioport_write (conf.port + 6, 10, 1, gus_writeb, s); |
|
|
|
register_ioport_write (conf.port + 6, 10, 2, gus_writew, s); |
|
|
|
register_ioport_read (conf.port + 6, 10, 1, gus_readb, s); |
|
|
|
register_ioport_read (conf.port + 6, 10, 2, gus_readw, s); |
|
|
|
register_ioport_write (s->port + 6, 10, 1, gus_writeb, s); |
|
|
|
register_ioport_write (s->port + 6, 10, 2, gus_writew, s); |
|
|
|
register_ioport_read (s->port + 6, 10, 1, gus_readb, s); |
|
|
|
register_ioport_read (s->port + 6, 10, 2, gus_readw, s); |
|
|
|
|
|
|
|
|
|
|
|
register_ioport_write (conf.port + 0x100, 8, 1, gus_writeb, s); |
|
|
|
register_ioport_write (conf.port + 0x100, 8, 2, gus_writew, s); |
|
|
|
register_ioport_read (conf.port + 0x100, 8, 1, gus_readb, s); |
|
|
|
register_ioport_read (conf.port + 0x100, 8, 2, gus_readw, s); |
|
|
|
register_ioport_write (s->port + 0x100, 8, 1, gus_writeb, s); |
|
|
|
register_ioport_write (s->port + 0x100, 8, 2, gus_writew, s); |
|
|
|
register_ioport_read (s->port + 0x100, 8, 1, gus_readb, s); |
|
|
|
register_ioport_read (s->port + 0x100, 8, 2, gus_readw, s); |
|
|
|
|
|
|
|
DMA_register_channel (conf.dma, GUS_read_DMA, s); |
|
|
|
s->emu.gusirq = conf.irq; |
|
|
|
s->emu.gusdma = conf.dma; |
|
|
|
s->emu.himemaddr = s->himem; |
|
|
|
s->emu.gusdatapos = s->emu.himemaddr + 1024 * 1024 + 32; |
|
|
|
s->emu.opaque = s; |
|
|
|
s->freq = conf.freq; |
|
|
|
s->pic = pic; |
|
|
|
isa_init_irq(dev, &s->pic, s->emu.gusirq); |
|
|
|
|
|
|
|
AUD_set_active_out (s->voice, 1); |
|
|
|
|
|
|
|
register_savevm ("gus", 0, 2, GUS_save, GUS_load, s); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int GUS_init (qemu_irq *pic) |
|
|
|
{ |
|
|
|
isa_create_simple("gus"); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static ISADeviceInfo gus_info = { |
|
|
|
.qdev.name = "gus", |
|
|
|
.qdev.desc = "Creative Sound Blaster 16", |
|
|
|
.qdev.size = sizeof (GUSState), |
|
|
|
.init = gus_initfn, |
|
|
|
.qdev.props = (Property[]) { |
|
|
|
DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100), |
|
|
|
DEFINE_PROP_HEX32 ("iobase", GUSState, port, 0x240), |
|
|
|
DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7), |
|
|
|
DEFINE_PROP_UINT32 ("dma", GUSState, emu.gusdma, 3), |
|
|
|
DEFINE_PROP_END_OF_LIST (), |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
static void gus_register(void) |
|
|
|
{ |
|
|
|
isa_qdev_register(&gus_info); |
|
|
|
} |
|
|
|
device_init(gus_register) |
|
|
|
|