Merge pull request #528 from Altheos/gus

GUS soundcard improvements
This commit is contained in:
OBattler
2020-01-12 18:51:56 +01:00
committed by GitHub
4 changed files with 249 additions and 139 deletions

View File

@@ -16,6 +16,36 @@
#include "midi.h"
#include "snd_gus.h"
enum
{
MIDI_INT_RECEIVE = 0x01,
MIDI_INT_TRANSMIT = 0x02,
MIDI_INT_MASTER = 0x80
};
enum
{
MIDI_CTRL_TRANSMIT_MASK = 0x60,
MIDI_CTRL_TRANSMIT = 0x20,
MIDI_CTRL_RECEIVE = 0x80
};
enum
{
GUS_INT_MIDI_TRANSMIT = 0x01,
GUS_INT_MIDI_RECEIVE = 0x02
};
enum
{
GUS_TIMER_CTRL_AUTO = 0x01
};
enum
{
GUS_CLASSIC = 0,
GUS_MAX = 1,
};
typedef struct gus_t
{
@@ -52,12 +82,14 @@ typedef struct gus_t
uint64_t samp_latch;
uint8_t *ram;
uint32_t gus_end_ram;
int irqnext;
pc_timer_t timer_1, timer_2;
int irq, dma, irq_midi;
uint16_t base;
int latch_enable;
uint8_t sb_2xa, sb_2xc, sb_2xe;
@@ -103,51 +135,26 @@ void pollgusirqs(gus_t *gus)
gus->irqstatus2=0x60|c;
if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
gus->irqstatus|=0x20;
if (gus->irq != 0)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
return;
}
if (gus->rampirqs[c])
{
gus->irqstatus2=0xA0|c;
gus->irqstatus|=0x40;
if (gus->irq != 0)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
return;
}
}
gus->irqstatus2=0xE0;
if (!gus->irqstatus) {
if (gus->irq != 0)
picintc(1 << gus->irq);
}
if (gus->irq != 0)
picintc(1 << gus->irq);
}
}
enum
{
MIDI_INT_RECEIVE = 0x01,
MIDI_INT_TRANSMIT = 0x02,
MIDI_INT_MASTER = 0x80
};
enum
{
MIDI_CTRL_TRANSMIT_MASK = 0x60,
MIDI_CTRL_TRANSMIT = 0x20,
MIDI_CTRL_RECEIVE = 0x80
};
enum
{
GUS_INT_MIDI_TRANSMIT = 0x01,
GUS_INT_MIDI_RECEIVE = 0x02
};
enum
{
GUS_TIMER_CTRL_AUTO = 0x01
};
void gus_midi_update_int_status(gus_t *gus)
{
gus->midi_status &= ~MIDI_INT_MASTER;
@@ -161,8 +168,8 @@ void gus_midi_update_int_status(gus_t *gus)
if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE))
{
gus->midi_status |= MIDI_INT_MASTER;
gus->irqstatus |= GUS_INT_MIDI_RECEIVE;
gus->midi_status |= MIDI_INT_MASTER;
gus->irqstatus |= GUS_INT_MIDI_RECEIVE;
}
else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
@@ -178,42 +185,46 @@ void writegus(uint16_t addr, uint8_t val, void *p)
gus_t *gus = (gus_t *)p;
int c, d;
int old;
switch (addr)
uint16_t port;
if ((addr == 0x388) || (addr == 0x389))
port = addr;
else
port = addr & 0xf0f;
switch (port)
{
case 0x340: /*MIDI control*/
old = gus->midi_ctrl;
gus->midi_ctrl = val;
gus->uart_out = 1;
if ((val & 3) == 3) { /*Master reset*/
gus->uart_in = 0;
gus->midi_status = 0;
gus->midi_r = 0;
gus->midi_w = 0;
} else if ((old & 3) == 3) {
gus->midi_status |= MIDI_INT_TRANSMIT;
} else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) {
gus->uart_in = 1;
}
gus_midi_update_int_status(gus);
case 0x300: /*MIDI control*/
old = gus->midi_ctrl;
gus->midi_ctrl = val;
gus->uart_out = 1;
if ((val & 3) == 3) { /*Master reset*/
gus->uart_in = 0;
gus->midi_status = 0;
gus->midi_r = 0;
gus->midi_w = 0;
} else if ((old & 3) == 3) {
gus->midi_status |= MIDI_INT_TRANSMIT;
} else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) {
gus->uart_in = 1;
}
gus_midi_update_int_status(gus);
break;
case 0x341: /*MIDI data*/
gus->midi_data = val;
case 0x301: /*MIDI data*/
gus->midi_data = val;
if (gus->uart_out) {
midi_raw_out_byte(val);
midi_raw_out_byte(val);
}
if (gus->latch_enable & 0x20) {
gus->midi_status |= MIDI_INT_RECEIVE;
} else
gus->midi_status |= MIDI_INT_TRANSMIT;
if (gus->latch_enable & 0x20) {
gus->midi_status |= MIDI_INT_RECEIVE;
} else
gus->midi_status |= MIDI_INT_TRANSMIT;
break;
case 0x342: /*Voice select*/
gus->voice = val & 31;
case 0x303: /*Global select*/
gus->global=val;
break;
case 0x343: /*Global select*/
gus->global = val;
break;
case 0x344: /*Global low*/
case 0x304: /*Global low*/
switch (gus->global)
{
case 0: /*Voice control*/
@@ -265,7 +276,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
break;
}
break;
case 0x345: /*Global high*/
case 0x305: /*Global high*/
switch (gus->global)
{
case 0: /*Voice control*/
@@ -451,11 +462,12 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
break;
}
break;
case 0x347: /*DRAM access*/
gus->ram[gus->addr]=val;
case 0x307: /*DRAM access*/
gus->addr&=0xFFFFF;
if (gus->addr < gus->gus_end_ram)
gus->ram[gus->addr]=val;
break;
case 0x248: case 0x388:
case 0x208: case 0x388:
gus->adcommand = val;
break;
@@ -495,11 +507,11 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
break;
case 0x240:
case 0x200:
gus->latch_enable = val;
break;
case 0x24b:
case 0x20b:
switch (gus->reg_ctrl & 0x07)
{
case 0:
@@ -586,19 +598,19 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
break;
case 0x246:
case 0x206:
if (gus->sb_ctrl & 0x20) {
gus->ad_status |= 0x08;
gus->ad_status |= 0x08;
if (gus->sb_nmi)
nmi = 1;
nmi = 1;
else if (gus->irq != 0)
picint(1 << gus->irq);
picint(1 << gus->irq);
}
break;
case 0x24a:
case 0x20a:
gus->sb_2xa = val;
break;
case 0x24c:
case 0x20c:
gus->ad_status |= 0x10;
if (gus->sb_ctrl & 0x20)
{
@@ -607,29 +619,37 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
else if (gus->irq != 0)
picint(1 << gus->irq);
}
case 0x24d:
case 0x20d:
gus->sb_2xc = val;
break;
case 0x24e:
case 0x20e:
gus->sb_2xe = val;
break;
case 0x24f:
case 0x20f:
gus->reg_ctrl = val;
break;
}
}
uint8_t readgus(uint16_t addr, void *p)
{
gus_t *gus = (gus_t *)p;
uint8_t val = 0xff;
switch (addr)
uint16_t port;
if ((addr == 0x388) || (addr == 0x389))
port = addr;
else
port = addr & 0xf0f;
switch (port)
{
case 0x340: /*MIDI status*/
case 0x300: /*MIDI status*/
val = gus->midi_status;
break;
case 0x341: /*MIDI data*/
case 0x301: /*MIDI data*/
val = 0;
if (gus->uart_in) {
if ((gus->midi_data == 0xaa) && (gus->midi_ctrl & MIDI_CTRL_RECEIVE)) /*Handle master reset*/
@@ -646,29 +666,29 @@ uint8_t readgus(uint16_t addr, void *p)
}
break;
case 0x240:
val = 0xff;
break;
case 0x200:
val = 0xff;
break;
case 0x246: /*IRQ status*/
case 0x206: /*IRQ status*/
val = gus->irqstatus & ~0x10;
if (gus->ad_status & 0x19)
val |= 0x10;
break;
case 0x24F:
val = 0;
break;
case 0x20F:
val = 0;
break;
case 0x342:
val = gus->voice;
break;
case 0x302:
val = gus->voice;
break;
case 0x343:
val = gus->global;
break;
case 0x303:
val = gus->global;
break;
case 0x344: /*Global low*/
case 0x304: /*Global low*/
switch (gus->global)
{
case 0x82: /*Start addr high*/
@@ -698,7 +718,7 @@ uint8_t readgus(uint16_t addr, void *p)
break;
}
break;
case 0x345: /*Global high*/
case 0x305: /*Global high*/
switch (gus->global)
{
case 0x80: /*Voice control*/
@@ -747,16 +767,20 @@ uint8_t readgus(uint16_t addr, void *p)
break;
}
break;
case 0x346: return 0xff;
case 0x347: /*DRAM access*/
case 0x306: case 0x706: /*Revision level*/
val = 0xff;
break;
case 0x307: /*DRAM access*/
val=gus->ram[gus->addr];
gus->addr&=0xFFFFF;
return val;
case 0x349: return 0;
case 0x746: /*Revision level*/
return 0xff; /*Pre 3.7 - no mixer*/
if (gus->addr < gus->gus_end_ram)
val = gus->ram[gus->addr];
else
val = 0;
break;
case 0x309: return 0;
case 0x24b:
case 0x20b:
switch (gus->reg_ctrl & 0x07)
{
case 1:
@@ -774,15 +798,15 @@ uint8_t readgus(uint16_t addr, void *p)
}
break;
case 0x24c:
case 0x20c:
val = gus->sb_2xc;
if (gus->reg_ctrl & 0x20)
gus->sb_2xc &= 0x80;
break;
case 0x24e:
case 0x20e:
return gus->sb_2xe;
case 0x248: case 0x388:
case 0x208: case 0x388:
if (gus->tctrl & GUS_TIMER_CTRL_AUTO)
val = gus->sb_2xa;
else
@@ -793,14 +817,14 @@ uint8_t readgus(uint16_t addr, void *p)
}
break;
case 0x249:
case 0x209:
gus->ad_status &= ~0x01;
nmi = 0;
case 0x389:
val = gus->ad_data;
break;
case 0x24A:
case 0x20A:
val = gus->adcommand;
break;
@@ -822,9 +846,9 @@ void gus_poll_timer_1(void *p)
gus->ad_status |= 0x40;
if (gus->tctrl&4)
{
if (gus->irq != 0)
picint(1 << gus->irq);
gus->ad_status |= 0x04;
if (gus->irq != 0)
picint(1 << gus->irq);
gus->ad_status |= 0x04;
gus->irqstatus |= 0x04;
}
}
@@ -833,8 +857,8 @@ void gus_poll_timer_1(void *p)
{
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != 0)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
}
gus_midi_update_int_status(gus);
@@ -854,8 +878,8 @@ void gus_poll_timer_2(void *p)
gus->ad_status |= 0x20;
if (gus->tctrl&8)
{
if (gus->irq != 0)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
gus->ad_status |= 0x02;
gus->irqstatus |= 0x08;
}
@@ -866,7 +890,7 @@ void gus_poll_timer_2(void *p)
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != 0)
picint(1 << gus->irq);
picint(1 << gus->irq);
}
}
@@ -1109,11 +1133,13 @@ void *gus_init(const device_t *info)
{
int c;
double out = 1.0;
uint8_t gus_ram = device_get_config_int("gus_ram");
gus_t *gus = malloc(sizeof(gus_t));
memset(gus, 0, sizeof(gus_t));
gus->ram = malloc(1 << 20);
memset(gus->ram, 0, 1 << 20);
gus->gus_end_ram = 1 << (18 + gus_ram);
gus->ram = (uint8_t *)malloc(gus->gus_end_ram);
memset(gus->ram, 0x00, (gus->gus_end_ram));
for (c=0;c<32;c++)
{
@@ -1132,12 +1158,14 @@ void *gus_init(const device_t *info)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
gus->t1l = gus->t2l = 0xff;
gus->uart_out = 1;
io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
gus->uart_out = 1;
gus->base = device_get_config_hex16("base");
io_sethandler(gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
@@ -1145,9 +1173,9 @@ void *gus_init(const device_t *info)
sound_add_handler(gus_get_buffer, gus);
input_msg = gus_input_msg;
input_sysex = gus_input_sysex;
midi_in_p = gus;
input_msg = gus_input_msg;
input_sysex = gus_input_sysex;
midi_in_p = gus;
return gus;
}
@@ -1170,11 +1198,76 @@ void gus_speed_changed(void *p)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
}
static const device_config_t gus_config[] = {
{
"type", "GUS type", CONFIG_SELECTION, "", 0,
{
{
"Classic", GUS_CLASSIC
},
#if 0
{
"MAX", GUS_MAX
},
#endif
{
NULL
}
},
},
{
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"210H", 0x210
},
{
"220H", 0x220
},
{
"230H", 0x230
},
{
"240H", 0x240
},
{
"250H", 0x250
},
{
"260H", 0x260
},
},
},
{
"gus_ram", "Onboard RAM", CONFIG_SELECTION, "", 0,
{
{
"256 KB", 0
},
{
"512 KB", 1
},
{
"1 MB", 2
},
{
NULL
}
}
},
{
"", "", -1
}
};
const device_t gus_device =
{
"Gravis UltraSound",
0, 0,
gus_init, gus_close, NULL, NULL,
gus_speed_changed, NULL,
NULL
DEVICE_ISA,
0,
gus_init, gus_close, NULL,
NULL,
gus_speed_changed,
NULL,
gus_config
};

View File

@@ -366,7 +366,7 @@ BEGIN
PUSHBUTTON "Joystick 4...",IDC_JOY4,209,44,50,14
END
DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 116
DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 199
STYLE DS_CONTROL | WS_CHILD
FONT 9, "Segoe UI"
BEGIN
@@ -395,9 +395,11 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,147,83,94,10
CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,101,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10
PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,99,46,12
CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,147,101,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,7,115,94,10
END
DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63

View File

@@ -149,8 +149,8 @@
#define IDC_CHECK_MPU401 1076
#define IDC_CONFIGURE_MPU401 1077
#define IDC_CHECK_FLOAT 1078
#define IDC_CHECK_GUSMAX 1079
#define IDC_COMBO_MIDI_IN 1080
#define IDC_CONFIGURE_GUS 1079
#define IDC_COMBO_MIDI_IN 1080
#define IDC_COMBO_NET_TYPE 1090 /* network config */
#define IDC_COMBO_PCAP 1091

View File

@@ -56,6 +56,7 @@
#include "../sound/sound.h"
#include "../sound/midi.h"
#include "../sound/snd_mpu401.h"
#include "../sound/snd_gus.h"
#include "../video/video.h"
#include "../video/vid_voodoo.h"
#include "../plat.h"
@@ -1117,7 +1118,6 @@ mpu401_standalone_allow(void)
return 1;
}
#if defined(__amd64__) || defined(__aarch64__)
static LRESULT CALLBACK
#else
@@ -1245,7 +1245,10 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
h=GetDlgItem(hdlg, IDC_CHECK_GUS);
SendMessage(h, BM_SETCHECK, temp_GUS, 0);
h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS);
EnableWindow(h, (temp_GUS) ? TRUE : FALSE);
h=GetDlgItem(hdlg, IDC_CHECK_SSI);
SendMessage(h, BM_SETCHECK, temp_SSI2001, 0);
@@ -1345,6 +1348,18 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
temp_deviceconfig |= deviceconfig_open(hdlg, (machines[temp_machine].flags & MACHINE_MCA) ?
(void *)&mpu401_mca_device : (void *)&mpu401_device);
break;
case IDC_CHECK_GUS:
h = GetDlgItem(hdlg, IDC_CHECK_GUS);
temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS);
EnableWindow(h, temp_GUS ? TRUE : FALSE);
break;
case IDC_CONFIGURE_GUS:
temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&gus_device);
break;
}
return FALSE;