From 9632f99552a0c31ab91cd0b4f63963248800fe8c Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 4 Aug 2021 13:46:26 +0500 Subject: [PATCH 1/5] Make the Game Blaster's I/O address configurable --- src/include/86box/resource.h | 1 + src/sound/snd_cms.c | 38 ++++++++++++++++++++++++++++++++++-- src/win/86Box.rc | 10 ++++++---- src/win/win_settings.c | 11 +++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 7ce6edd18..3e5754e36 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -163,6 +163,7 @@ #define IDC_CHECK_FLOAT 1048 #define IDC_CONFIGURE_GUS 1049 #define IDC_COMBO_MIDI_IN 1050 +#define IDC_CONFIGURE_CMS 1051 #define IDC_COMBO_NET_TYPE 1060 /* network config */ #define IDC_COMBO_PCAP 1061 diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 61278fa88..dae1f735f 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -181,7 +181,8 @@ void *cms_init(const device_t *info) cms_t *cms = malloc(sizeof(cms_t)); memset(cms, 0, sizeof(cms_t)); - io_sethandler(0x0220, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); + uint16_t addr = device_get_config_hex16("base"); + io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms); sound_add_handler(cms_get_buffer, cms); return cms; } @@ -193,11 +194,44 @@ void cms_close(void *p) free(cms); } +static const device_config_t cms_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, + { + { + "0x210", 0x210 + }, + { + "0x220", 0x220 + }, + { + "0x230", 0x230 + }, + { + "0x240", 0x240 + }, + { + "0x250", 0x250 + }, + { + "0x260", 0x260 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + const device_t cms_device = { "Creative Music System / Game Blaster", 0, 0, cms_init, cms_close, NULL, { NULL }, NULL, NULL, - NULL + cms_config }; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 2ee41aec1..736bd33b4 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -517,15 +517,17 @@ BEGIN CONTROL "Innovation SSI-2001",IDC_CHECK_SSI,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,84,95,10 + CONTROL "CMS / Game Blaster",IDC_CHECK_CMS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,84,95,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,102,95,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_CMS,214,100,46,12 CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,101,94,10 - PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,101,46,12 + BS_AUTOCHECKBOX | WS_TABSTOP,7,120,94,10 + PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,118,46,12 CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,117,94,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,138,94,10 END DLG_CFG_NETWORK DIALOG DISCARDABLE 107, 0, 267, 65 diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 811493a6a..4a7dbc0bb 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -1376,6 +1376,7 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_CHECK_MPU401, mpu401_standalone_allow()); settings_enable_window(hdlg, IDC_CONFIGURE_MPU401, mpu401_standalone_allow() && temp_mpu401); settings_set_check(hdlg, IDC_CHECK_CMS, temp_GAMEBLASTER); + settings_enable_window(hdlg, IDC_CONFIGURE_CMS, temp_GAMEBLASTER); settings_set_check(hdlg, IDC_CHECK_GUS, temp_GUS); settings_enable_window(hdlg, IDC_CONFIGURE_GUS, temp_GUS); settings_set_check(hdlg, IDC_CHECK_SSI, temp_SSI2001); @@ -1437,6 +1438,16 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) (void *)&mpu401_mca_device : (void *)&mpu401_device); break; + case IDC_CHECK_CMS: + temp_GAMEBLASTER = settings_get_check(hdlg, IDC_CHECK_CMS); + + settings_enable_window(hdlg, IDC_CONFIGURE_CMS, temp_GAMEBLASTER); + break; + + case IDC_CONFIGURE_CMS: + temp_deviceconfig |= deviceconfig_open(hdlg, &cms_device); + break; + case IDC_CHECK_GUS: temp_GUS = settings_get_check(hdlg, IDC_CHECK_GUS); settings_enable_window(hdlg, IDC_CONFIGURE_GUS, temp_GUS); From 06eda55634ad9638f1f0632f7f5ba75ea6137a46 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 4 Aug 2021 13:48:41 +0500 Subject: [PATCH 2/5] Move some CMS definitions and function declarations to a header file --- src/include/86box/snd_cms.h | 35 +++++++++++++++++++++++++++++++++++ src/sound/snd_cms.c | 25 +------------------------ 2 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 src/include/86box/snd_cms.h diff --git a/src/include/86box/snd_cms.h b/src/include/86box/snd_cms.h new file mode 100644 index 000000000..8700bf873 --- /dev/null +++ b/src/include/86box/snd_cms.h @@ -0,0 +1,35 @@ +#ifndef SOUND_SND_CMS_H +# define SOUND_SND_CMS_H + +#include +#include <86box/sound.h> + +#define MASTER_CLOCK 7159090 + +typedef struct cms_t +{ + int addrs[2]; + uint8_t regs[2][32]; + uint16_t latch[2][6]; + int freq[2][6]; + float count[2][6]; + int vol[2][6][2]; + int stat[2][6]; + uint16_t noise[2][2]; + uint16_t noisefreq[2][2]; + int noisecount[2][2]; + int noisetype[2][2]; + + uint8_t latched_data; + + int16_t buffer[SOUNDBUFLEN * 2]; + + int pos; +} cms_t; + + +extern void cms_update(cms_t *cms); +extern void cms_write(uint16_t addr, uint8_t val, void *p); +extern uint8_t cms_read(uint16_t addr, void *p); + +#endif /*SOUND_SND_CMS_H*/ diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index dae1f735f..631e00c6a 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -9,32 +9,9 @@ #include <86box/io.h> #include <86box/device.h> #include <86box/sound.h> +#include <86box/snd_cms.h> -#define MASTER_CLOCK 7159090 - - -typedef struct cms_t -{ - int addrs[2]; - uint8_t regs[2][32]; - uint16_t latch[2][6]; - int freq[2][6]; - float count[2][6]; - int vol[2][6][2]; - int stat[2][6]; - uint16_t noise[2][2]; - uint16_t noisefreq[2][2]; - int noisecount[2][2]; - int noisetype[2][2]; - - uint8_t latched_data; - - int16_t buffer[SOUNDBUFLEN * 2]; - - int pos; -} cms_t; - void cms_update(cms_t *cms) { for (; cms->pos < sound_pos_global; cms->pos++) From e41d473f43c0563d726aa0e3339ea580a92da463 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 4 Aug 2021 13:51:00 +0500 Subject: [PATCH 3/5] Add the CMS emulation to the SB 1.0, 1.5 and 2.0 --- src/include/86box/snd_sb.h | 4 +- src/sound/snd_sb.c | 151 +++++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 23 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 8641a58f2..7291aa4d0 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -22,6 +22,7 @@ #include <86box/snd_mpu401.h> #include <86box/snd_opl.h> #include <86box/snd_sb_dsp.h> +#include <86box/snd_cms.h> #define SADLIB 1 /* No DSP */ #define SB1 2 /* DSP v1.05 */ @@ -111,7 +112,8 @@ typedef struct sb_ct1745_mixer_t typedef struct sb_t { - uint8_t opl_enabled, mixer_enabled; + uint8_t cms_enabled, opl_enabled, mixer_enabled; + cms_t cms; opl_t opl, opl2; sb_dsp_t dsp; union { diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 70669008f..37f8ccfec 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -186,34 +186,53 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *p) sb_t *sb = (sb_t *) p; sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; int c; - double out = 0.0; + double out_mono = 0.0, out_l = 0.0, out_r = 0.0; if (sb->opl_enabled) opl2_update(&sb->opl); sb_dsp_update(&sb->dsp); - for (c = 0; c < len * 2; c += 2) { - out = 0.0; + if (sb->cms_enabled) + cms_update(&sb->cms); - if (sb->opl_enabled) { - out = ((double) sb->opl.buffer[c]) * 0.7171630859375; - if (sb->mixer_enabled) - out *= mixer->fm; + for (c = 0; c < len * 2; c += 2) { + out_mono = 0.0; + out_l = 0.0; + out_r = 0.0; + + if (sb->opl_enabled) + out_mono = ((double) sb->opl.buffer[c]) * 0.7171630859375; + + if (sb->cms_enabled) { + out_l += sb->cms.buffer[c]; + out_r += sb->cms.buffer[c + 1]; + } + out_l += out_mono; + out_r += out_mono; + + if (((sb->opl_enabled) || (sb->cms_enabled)) && sb->mixer_enabled) { + out_l *= mixer->fm; + out_r *= mixer->fm; } /* TODO: Recording: I assume it has direct mic and line in like SB2. It is unclear from the docs if it has a filter, but it probably does. */ /* TODO: Recording: Mic and line In with AGC. */ + if (sb->mixer_enabled) + out_mono = (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice) / 3.9; + else + out_mono = (((sb_iir(0, 0, (double) sb->dsp.buffer[c]) / 1.3) * 65536.0) / 3.0) / 65536.0; + out_l += out_mono; + out_r += out_mono; + if (sb->mixer_enabled) { - out += (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice) / 3.9; + out_l *= mixer->master; + out_r *= mixer->master; + } - out *= mixer->master; - } else - out += (((sb_iir(0, 0, (double) sb->dsp.buffer[c]) / 1.3) * 65536.0) / 3.0) / 65536.0; - - buffer[c] += (int32_t) out; - buffer[c + 1] += (int32_t) out; + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; } sb->pos = 0; @@ -222,6 +241,9 @@ sb_get_buffer_sb2(int32_t *buffer, int len, void *p) sb->opl.pos = 0; sb->dsp.pos = 0; + + if (sb->cms_enabled) + sb->cms.pos = 0; } @@ -1261,8 +1283,7 @@ sb_1_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - /* CMS I/O handler is activated on the dedicated sound_cms module - DSP I/O handler is activated in sb_dsp_setaddr */ + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); @@ -1270,6 +1291,10 @@ sb_1_init(const device_t *info) opl2_write, NULL, NULL, &sb->opl); } + sb->cms_enabled = 1; + memset(&sb->cms, 0, sizeof(cms_t)); + io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); @@ -1300,8 +1325,7 @@ sb_15_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - /* CMS I/O handler is activated on the dedicated sound_cms module - DSP I/O handler is activated in sb_dsp_setaddr */ + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); @@ -1309,6 +1333,12 @@ sb_15_init(const device_t *info) opl2_write, NULL, NULL, &sb->opl); } + sb->cms_enabled = device_get_config_int("cms"); + if (sb->cms_enabled) { + memset(&sb->cms, 0, sizeof(cms_t)); + io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + } + sb->mixer_enabled = 0; sound_add_handler(sb_get_buffer_sb2, sb); sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); @@ -1385,10 +1415,11 @@ sb_2_init(const device_t *info) sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); if (mixer_addr > 0x000) sb_ct1335_mixer_reset(sb); - /* CMS I/O handler is activated on the dedicated sound_cms module - DSP I/O handler is activated in sb_dsp_setaddr */ + + sb->cms_enabled = device_get_config_int("cms"); + /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { - if (!GAMEBLASTER) { + if (!sb->cms_enabled) { io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } @@ -1398,6 +1429,11 @@ sb_2_init(const device_t *info) opl2_write, NULL, NULL, &sb->opl); } + if (sb->cms_enabled) { + memset(&sb->cms, 0, sizeof(cms_t)); + io_sethandler(addr, 0x0004, cms_read, NULL, NULL, cms_write, NULL, NULL, &sb->cms); + } + if (mixer_addr > 0x000) { sb->mixer_enabled = 1; io_sethandler(addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, @@ -1926,6 +1962,74 @@ static const device_config_t sb_config[] = }; +static const device_config_t sb15_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 }, + { + { + "0x220", 0x220 + }, + { + "0x240", 0x240 + }, + { + "0x260", 0x260 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 7, "", { 0 }, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "" + } + } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 1, "", { 0 }, + { + { + "DMA 1", 1 + }, + { + "DMA 3", 3 + }, + { + "" + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + "cms", "Enable CMS", CONFIG_BINARY, "", 0 + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } +}; + + static const device_config_t sb2_config[] = { { @@ -2002,6 +2106,9 @@ static const device_config_t sb2_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "cms", "Enable CMS", CONFIG_BINARY, "", 0 + }, { "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 }, @@ -2509,7 +2616,7 @@ const device_t sb_15_device = sb_15_init, sb_close, NULL, { NULL }, sb_speed_changed, NULL, - sb_config + sb15_config }; const device_t sb_mcv_device = From 8184c411df774009f214c2b8f8a0d8dbf26f1a43 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 4 Aug 2021 13:51:52 +0500 Subject: [PATCH 4/5] Fix the SB 2.0 mixer address selection and add a 0x250 address option --- src/sound/snd_sb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 37f8ccfec..e1068b8a3 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1436,7 +1436,7 @@ sb_2_init(const device_t *info) if (mixer_addr > 0x000) { sb->mixer_enabled = 1; - io_sethandler(addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, + io_sethandler(mixer_addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, sb_ct1335_mixer_write, NULL, NULL, sb); } else sb->mixer_enabled = 0; @@ -2061,6 +2061,9 @@ static const device_config_t sb2_config[] = { "0x240", 0x240 }, + { + "0x250", 0x250 + }, { "0x260", 0x260 }, From b1a8c297e1a81cf37dad9e6d897b72f1e213edaf Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 5 Aug 2021 13:32:44 +0500 Subject: [PATCH 5/5] Disable the SB 2.0 mixer by default --- src/sound/snd_sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index e1068b8a3..cdec4c7c2 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -2050,7 +2050,7 @@ static const device_config_t sb2_config[] = } }, { - "mixaddr", "Mixer", CONFIG_HEX16, "", 0x220, "", { 0 }, + "mixaddr", "Mixer", CONFIG_HEX16, "", 0, "", { 0 }, { { "Disabled", 0