diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 9399c3dc5..1f8fcfd3b 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -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 }; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 43c2c0f7c..851b7d287 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -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 diff --git a/src/win/resource.h b/src/win/resource.h index 49ba9679e..8e11ed62a 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -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 diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 1a2605a07..f47f4f4b1 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -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;