diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..2ed0e4596 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,19 @@ +Summary +======= +_Briefly describe what you are submitting._ + +Approach +======== +_How did you address the problem?_ + +Checklist +========= +* [ ] Closes issue #xxx +* [ ] I have discussed this with core contributors already +* [ ] This pull request requires inclusion of a ROM in the romset + * [ ] I have opened a roms pull request - https://github.com/86Box/roms/pull/changeme/ +* [ ] My commit messages are descriptive and I have not added any irrelevant files to the repository + +References +========== +_Provide links to datasheets or other documentation that helped you implement this pull request._ diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index e85bc5191..fae8f255f 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -35,10 +35,14 @@ #include <86box/chipset.h> #include <86box/spd.h> +#define VIA_597 0x05970100 +#define VIA_598 0x05980000 +#define VIA_691 0x06910000 +#define VIA_8601 0x86010500 typedef struct via_apollo_t { - uint16_t id; + uint32_t id; uint8_t pci_conf[256]; smram_t *smram; @@ -84,8 +88,8 @@ via_apollo_setup(via_apollo_t *dev) /* Host Bridge */ dev->pci_conf[0x00] = 0x06; /*VIA*/ dev->pci_conf[0x01] = 0x11; - dev->pci_conf[0x02] = dev->id & 0xff; - dev->pci_conf[0x03] = (dev->id >> 8); + dev->pci_conf[0x02] = dev->id >> 16; + dev->pci_conf[0x03] = dev->id >> 24; dev->pci_conf[0x04] = 6; dev->pci_conf[0x05] = 0; @@ -93,8 +97,7 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x06] = 0x90; dev->pci_conf[0x07] = 0x02; - if (dev->id == 0x0597) - dev->pci_conf[0x08] = 1; /* Production Silicon ("Revision B") */ + dev->pci_conf[0x08] = dev->id >> 8; dev->pci_conf[0x09] = 0; dev->pci_conf[0x0a] = 0; dev->pci_conf[0x0b] = 6; @@ -105,7 +108,9 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x10] = 0x08; dev->pci_conf[0x34] = 0xa0; - if (dev->id == 0x0691) { + if (dev->id == VIA_8601) + dev->pci_conf[0x52] = 0x10; + if (dev->id == VIA_691) { dev->pci_conf[0x56] = 0x01; dev->pci_conf[0x57] = 0x01; } @@ -119,7 +124,7 @@ via_apollo_setup(via_apollo_t *dev) dev->pci_conf[0x64] = 0xec; dev->pci_conf[0x65] = 0xec; dev->pci_conf[0x66] = 0xec; - if (dev->id == 0x0691) + if (dev->id == VIA_691) dev->pci_conf[0x67] = 0xec; /* DRAM Timing for Banks 6,7. */ dev->pci_conf[0x6b] = 0x01; @@ -138,7 +143,7 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) if (func) return; - + /*Read-only addresses*/ if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || ((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) || @@ -148,9 +153,9 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) ((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) || (addr == 0xfd)) return; - if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == 0x0597)) + if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == VIA_597)) return; - if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id != 0x0691)) + if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id != VIA_691)) return; switch(addr) { @@ -161,7 +166,11 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[0x07] &= ~(val & 0xb0); break; case 0x0d: + if(dev->id == VIA_8601) dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); + else + dev->pci_conf[0x0d] = (dev->pci_conf[0x0d] & ~0x07) | (val & 0x07); + dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0x30) | ((val & 0x06) << 3); break; @@ -173,45 +182,51 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0x50: /* Cache Control 1 */ - if (dev->id == 0x0691) + if (dev->id == VIA_8601) + dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xd3) | (val & 0xd3); + else if (dev->id == VIA_691) dev->pci_conf[0x50] = val; else dev->pci_conf[0x50] = (dev->pci_conf[0x50] & ~0xf8) | (val & 0xf8); break; case 0x51: /* Cache Control 2 */ - if (dev->id == 0x0691) + if (dev->id >= VIA_691) dev->pci_conf[0x51] = val; else dev->pci_conf[0x51] = (dev->pci_conf[0x51] & ~0xeb) | (val & 0xeb); break; case 0x52: /* Non_Cacheable Control */ - if (dev->id == 0x0691) + if (dev->id == VIA_8601) + dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xdf) | (val & 0xdf); + else if (dev->id == VIA_691) dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0x9f) | (val & 0x9f); else dev->pci_conf[0x52] = (dev->pci_conf[0x52] & ~0xf5) | (val & 0xf5); break; case 0x53: /* System Performance Control */ - if (dev->id == 0x0691) + if (dev->id == VIA_8601) + dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xfc) | (val & 0xfc); + else if (dev->id == VIA_691) dev->pci_conf[0x53] = val; else dev->pci_conf[0x53] = (dev->pci_conf[0x53] & ~0xf0) | (val & 0xf0); break; case 0x56: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* DRAM Row Ending Address */ - if (dev->id >= 0x0691) + if (dev->id >= VIA_691) spd_write_drbs(dev->pci_conf, 0x5a, 0x56, 8); else if (addr >= 0x5a) spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, 8); break; case 0x58: - if (dev->id == 0x0597) + if ((dev->id == VIA_597) || (dev->id == VIA_8601)) dev->pci_conf[0x58] = (dev->pci_conf[0x58] & ~0xee) | (val & 0xee); else dev->pci_conf[0x58] = val; break; case 0x59: - if (dev->id == 0x0691) + if (dev->id == VIA_691) dev->pci_conf[0x59] = val; else dev->pci_conf[0x59] = (dev->pci_conf[0x59] & ~0xf0) | (val & 0xf0); @@ -248,7 +263,7 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); dev->pci_conf[0x63] = val; smram_disable_all(); - if (dev->id == 0x0691) switch (val & 0x03) { + if (dev->id >= VIA_691) switch (val & 0x03) { case 0x00: default: apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ @@ -271,21 +286,21 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) default: /* Disable SMI Address Redirection (default) */ apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); - if (dev->id == 0x0597) + if (dev->id == VIA_597) apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); break; case 0x01: /* Allow access to DRAM Axxxx-Bxxxx for both normal and SMI cycles */ apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - if (dev->id == 0x0597) + if (dev->id == VIA_597) apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 1); break; case 0x02: /* Reserved */ apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 3); - if (dev->id == 0x0597) { + if (dev->id == VIA_597) { /* SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx. */ apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); } @@ -294,38 +309,46 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x03: /* Allow SMI Axxxx-Bxxxx DRAM access */ apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); - if (dev->id == 0x0597) + if (dev->id == VIA_597) apollo_smram_map(dev, 1, 0x00030000, 0x00020000, 1); apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); break; } break; case 0x68: - if (dev->id == 0x0597) + if (dev->id == VIA_597) dev->pci_conf[0x68] = (dev->pci_conf[0x6b] & ~0xfe) | (val & 0xfe); - else if (dev->id == 0x0598) + else if ((dev->id == VIA_598) || (dev->id == VIA_8601)) dev->pci_conf[0x68] = val; else dev->pci_conf[0x68] = (dev->pci_conf[0x6b] & ~0xfd) | (val & 0xfd); break; + case 0x69: + if (dev->id == VIA_8601) + dev->pci_conf[0x69] = (dev->pci_conf[0x69] & ~0xfe) | (val & 0xfe); + else + dev->pci_conf[0x69] = val; + break; case 0x6b: - if (dev->id == 0x0691) + if (dev->id == VIA_8601) + dev->pci_conf[0x6b] = val; + else if (dev->id == VIA_691) dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xcf) | (val & 0xcf); else dev->pci_conf[0x6b] = (dev->pci_conf[0x6b] & ~0xc1) | (val & 0xc1); break; case 0x6c: - if (dev->id == 0x0597) + if ((dev->id == VIA_597) || (dev->id == VIA_8601)) dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x1f) | (val & 0x1f); - else if (dev->id == 0x0598) + else if (dev->id == VIA_598) dev->pci_conf[0x6c] = (dev->pci_conf[0x6c] & ~0x7f) | (val & 0x7f); else dev->pci_conf[0x6c] = val; break; case 0x6d: - if (dev->id == 0x0597) + if (dev->id == VIA_597) dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x0f) | (val & 0x0f); - else if (dev->id == 0x0598) + else if ((dev->id == VIA_598) || (dev->id == VIA_8601)) dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x7f) | (val & 0x7f); else dev->pci_conf[0x6d] = val; @@ -335,24 +358,52 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0x70: - if (dev->id == 0x0597) + if (dev->id == VIA_8601) + dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xdf) | (val & 0xdf); + else if (dev->id == VIA_597) dev->pci_conf[0x70] = (dev->pci_conf[0x70] & ~0xf1) | (val & 0xf1); else dev->pci_conf[0x70] = val; break; + case 0x73: + if (dev->id == VIA_8601) + dev->pci_conf[0x73] = (dev->pci_conf[0x73] & ~0x7f) | (val & 0x7f); + else + dev->pci_conf[0x73] = val; + break; case 0x74: - dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xc0) | (val & 0xc0); + if (dev->id == VIA_8601) + dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xdf) | (val & 0xdf); + else + dev->pci_conf[0x74] = (dev->pci_conf[0x74] & ~0xc0) | (val & 0xc0); break; case 0x75: - dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0xcf) | (val & 0xcf); + if (dev->id == VIA_8601) + dev->pci_conf[0x75] = val; + else + dev->pci_conf[0x75] = (dev->pci_conf[0x75] & ~0xcf) | (val & 0xcf); break; case 0x76: - dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xf0) | (val & 0xf0); + if (dev->id == VIA_8601) + dev->pci_conf[0x75] = val; + else + dev->pci_conf[0x76] = (dev->pci_conf[0x76] & ~0xf0) | (val & 0xf0); break; case 0x77: + if (dev->id != VIA_8601) dev->pci_conf[0x77] = (dev->pci_conf[0x77] & ~0xc0) | (val & 0xc0); break; + case 0x78: + dev->pci_conf[0x78] = (dev->pci_conf[0x78] & ~0xd5) | (val & 0xd5); + break; + case 0x79: + dev->pci_conf[0x79] = (dev->pci_conf[0x79] & ~0xfc) | (val & 0xfc); + break; + case 0x7a: + dev->pci_conf[0x7a] = (dev->pci_conf[0x7a] & ~0x89) | (val & 0x89); + break; case 0x7e: + if (dev->id != VIA_8601) dev->pci_conf[0x7e] = (dev->pci_conf[0x7e] & ~0x3f) | (val & 0x3f); break; @@ -361,14 +412,25 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) break; case 0x84: /* The datasheet first mentions 7-0 but then says 3-0 are reserved - - - minimum of 16 MB for the graphics aperture? */ - dev->pci_conf[0x84] = (dev->pci_conf[0x84] & ~0xf0) | (val & 0xf0); + - minimum of 16 MB for the graphics aperture? 8601 datasheet doesn't refer it. */ + if(dev->id == VIA_8601) + dev->pci_conf[0x84] = val; + else + dev->pci_conf[0x84] = (dev->pci_conf[0x84] & ~0xf0) | (val & 0xf0); break; case 0x88: - dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x07) | (val & 0x07); + if(dev->id == VIA_8601) + dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x06) | (val & 0x06); + else + dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x07) | (val & 0x07); break; case 0x89: - dev->pci_conf[0x89] = (dev->pci_conf[0x89] & ~0xf0) | (val & 0xf0); + case 0x8a: + case 0x8b: + if(dev->id == VIA_8601) + dev->pci_conf[addr] = val; + else + dev->pci_conf[0x89] = (dev->pci_conf[0x89] & ~0xf0) | (val & 0xf0); break; case 0xa8: @@ -378,13 +440,29 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[0xa9] = (dev->pci_conf[0xa9] & ~0x03) | (val & 0x03); break; case 0xac: + if(dev->id == VIA_8601) + dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x7f) | (val & 0x7f); + else + dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); + break; + case 0xad: dev->pci_conf[0xac] = (dev->pci_conf[0xac] & ~0x0f) | (val & 0x0f); break; + case 0xfc: - if (dev->id > 0x0597) + if (dev->id == VIA_8601) + dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x03) | (val & 0x03); + else if (dev->id > VIA_597) dev->pci_conf[0xfc] = (dev->pci_conf[0xfc] & ~0x01) | (val & 0x01); break; + case 0xfd: + if (dev->id == VIA_8601) + dev->pci_conf[0xfd] = (dev->pci_conf[0xfd] & ~0x07) | (val & 0x07); + else + dev->pci_conf[0xfd] = val; + break; + default: dev->pci_conf[addr] = val; break; @@ -442,17 +520,21 @@ via_apollo_init(const device_t *info) dev->id = info->local; switch (dev->id) { - case 0x0597: + case VIA_597: device_add(&via_vp3_agp_device); break; - case 0x0598: + case VIA_598: device_add(&via_mvp3_agp_device); break; - case 0x0691: + case VIA_691: device_add(&via_apro_agp_device); break; + + case VIA_8601: + device_add(&via_vt8601_agp_device); + break; } via_apollo_setup(dev); @@ -477,7 +559,7 @@ const device_t via_vp3_device = { "VIA Apollo VP3", DEVICE_PCI, - 0x0597, /*VT82C597*/ + VIA_597, /*VT82C597*/ via_apollo_init, via_apollo_close, via_apollo_reset, @@ -491,7 +573,7 @@ const device_t via_mvp3_device = { "VIA Apollo MVP3", DEVICE_PCI, - 0x0598, /*VT82C598MVP*/ + VIA_598, /*VT82C598MVP*/ via_apollo_init, via_apollo_close, via_apollo_reset, @@ -504,7 +586,20 @@ const device_t via_mvp3_device = const device_t via_apro_device = { "VIA Apollo Pro", DEVICE_PCI, - 0x0691, /*VT82C691*/ + VIA_691, /*VT82C691*/ + via_apollo_init, + via_apollo_close, + via_apollo_reset, + NULL, + NULL, + NULL, + NULL +}; + +const device_t via_vt8601_device = { + "VIA Apollo ProMedia", + DEVICE_PCI, + VIA_8601, /*VT8601*/ via_apollo_init, via_apollo_close, via_apollo_reset, diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 953bf2c2b..a90cf3fff 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -54,7 +54,6 @@ #include <86box/sio.h> #include <86box/hwm.h> - /* Most revision numbers (PCI-ISA bridge or otherwise) were lifted from PCI device listings on forums, as VIA's datasheets are not very helpful regarding those. */ #define VIA_PIPC_586A 0x05862500 @@ -268,8 +267,9 @@ pipc_reset_hard(void *priv) dev->power_regs[0x08] = 0x40; break; } - if (dev->local >= VIA_PIPC_686A) - dev->power_regs[0x42] = 0x40; /* external suspend-related pin, must be set */ + dev->power_regs[0x40] = 0x20; + + dev->power_regs[0x42] = 0xd0; dev->power_regs[0x48] = 0x01; if (dev->local >= VIA_PIPC_686A) @@ -761,7 +761,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv) break; case 0x42: - dev->power_regs[addr] = val & 0x0f; + dev->power_regs[addr] = (dev->power_regs[0x42] & ~0x0f) | (val & 0x0f); acpi_set_irq_line(dev->acpi, dev->power_regs[addr]); pclog("VIA SCI: %d\n", dev->power_regs[addr]); break; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 50ea5763e..087e66fa4 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -538,6 +538,7 @@ CPU cpus_PentiumS5[] = { {"Pentium 100/50", CPU_PENTIUM, fpus_internal, 100000000, 2.0, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, {"Pentium 100/66", CPU_PENTIUM, fpus_internal, 100000000, 1.5, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, {"Pentium 120", CPU_PENTIUM, fpus_internal, 120000000, 2.0, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, + {"Pentium 133", CPU_PENTIUM, fpus_internal, 133333333, 2.0, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, /*Intel Pentium OverDrive*/ {"Pentium OverDrive 125", CPU_PENTIUM, fpus_internal, 125000000, 3.0, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16}, diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index 1e66a339d..53e64f989 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -39,6 +39,7 @@ #define AGP_BRIDGE_VIA_597 0x11068597 #define AGP_BRIDGE_VIA_598 0x11068598 #define AGP_BRIDGE_VIA_691 0x11068691 +#define AGP_BRIDGE_VIA_8601 0x11068601 #define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106) #define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_VIA_597) @@ -227,6 +228,7 @@ pci_bridge_reset(void *priv) case AGP_BRIDGE_VIA_597: case AGP_BRIDGE_VIA_598: case AGP_BRIDGE_VIA_691: + case AGP_BRIDGE_VIA_8601: dev->regs[0x04] = 0x07; dev->regs[0x06] = 0x20; dev->regs[0x07] = 0x02; @@ -406,3 +408,17 @@ const device_t via_apro_agp_device = NULL, NULL }; + +const device_t via_vt8601_agp_device = +{ + "VIA Apollo ProMedia AGP Bridge", + DEVICE_PCI, + AGP_BRIDGE_VIA_8601, + pci_bridge_init, + NULL, + pci_bridge_reset, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index a6cdf8742..fd16d27c0 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -120,6 +120,7 @@ extern const device_t via_vpx_device; extern const device_t via_vp3_device; extern const device_t via_mvp3_device; extern const device_t via_apro_device; +extern const device_t via_vt8601_device; extern const device_t via_vt82c586b_device; extern const device_t via_vt82c596_device; extern const device_t via_vt82c596b_device; diff --git a/src/include/86box/filters.h b/src/include/86box/filters.h index 95354176e..ff11a05d4 100644 --- a/src/include/86box/filters.h +++ b/src/include/86box/filters.h @@ -1,186 +1,5 @@ #define NCoef 2 -/* fc=350Hz */ -static inline float low_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { - 0.00049713569693400649, - 0.00099427139386801299, - 0.00049713569693400649 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -1.93522955470669530000, - 0.93726236021404663000 - }; - - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; - - /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; - } - - /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - - return y[i][0]; -} - -/* fc=350Hz */ -static inline float low_cut_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { - 0.96839970114733542000, - -1.93679940229467080000, - 0.96839970114733542000 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -1.93522955471202770000, - 0.93726236021916731000 - }; - - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; - - /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; - } - - /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - - return y[i][0]; -} - -/* fc=3.5kHz */ -static inline float high_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { - 0.72248704753064896000, - -1.44497409506129790000, - 0.72248704753064896000 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -1.36640781670578510000, - 0.52352474706139873000 - }; - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; - - /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; - } - - /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - - return y[i][0]; -} - -/* fc=3.5kHz */ -static inline float high_cut_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { - 0.03927726802250377400, - 0.07855453604500754700, - 0.03927726802250377400 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -1.36640781666419950000, - 0.52352474703279628000 - }; - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; - - /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; - } - - /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - - return y[i][0]; -} - - -#undef NCoef -#define NCoef 2 - -/* fc=3.2kHz */ -static inline float sb_iir(int i, float NewSample) { - float ACoef[NCoef+1] = { - 0.03356837051492005100, - 0.06713674102984010200, - 0.03356837051492005100 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -1.41898265221812010000, - 0.55326988968868285000 - }; - -/* float ACoef[NCoef+1] = { - 0.17529642630084405000, - 0.17529642630084405000 - }; - - float BCoef[NCoef+1] = { - 1.00000000000000000000, - -0.64940759319751051000 - };*/ - static float y[2][NCoef+1]; /* output samples */ - static float x[2][NCoef+1]; /* input samples */ - int n; - - /* shift the old samples */ - for(n=NCoef; n>0; n--) { - x[i][n] = x[i][n-1]; - y[i][n] = y[i][n-1]; - } - - /* Calculate the new output */ - x[i][0] = NewSample; - y[i][0] = ACoef[0] * x[i][0]; - for(n=1; n<=NCoef; n++) - y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n]; - - return y[i][0]; -} - - - -#undef NCoef -#define NCoef 2 - /* fc=150Hz */ static inline float adgold_highpass_iir(int i, float NewSample) { float ACoef[NCoef+1] = { @@ -347,30 +166,204 @@ static inline float dac_iir(int i, float NewSample) { } +#undef NCoef +#define NCoef 2 + +/* fc=350Hz */ +static inline double low_iir(int c, int i, double NewSample) { + double ACoef[NCoef+1] = { + 0.00049713569693400649, + 0.00099427139386801299, + 0.00049713569693400649 + }; + + double BCoef[NCoef+1] = { + 1.00000000000000000000, + -1.93522955470669530000, + 0.93726236021404663000 + }; + + static double y[2][2][NCoef+1]; /* output samples */ + static double x[2][2][NCoef+1]; /* input samples */ + int n; + + /* shift the old samples */ + for(n=NCoef; n>0; n--) { + x[c][i][n] = x[c][i][n-1]; + y[c][i][n] = y[c][i][n-1]; + } + + /* Calculate the new output */ + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; + for(n=1; n<=NCoef; n++) + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; + + return y[c][i][0]; +} + +/* fc=350Hz */ +static inline double low_cut_iir(int c, int i, double NewSample) { + double ACoef[NCoef+1] = { + 0.96839970114733542000, + -1.93679940229467080000, + 0.96839970114733542000 + }; + + double BCoef[NCoef+1] = { + 1.00000000000000000000, + -1.93522955471202770000, + 0.93726236021916731000 + }; + + static double y[2][2][NCoef+1]; /* output samples */ + static double x[2][2][NCoef+1]; /* input samples */ + int n; + + /* shift the old samples */ + for(n=NCoef; n>0; n--) { + x[c][i][n] = x[c][i][n-1]; + y[c][i][n] = y[c][i][n-1]; + } + + /* Calculate the new output */ + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; + for(n=1; n<=NCoef; n++) + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; + + return y[c][i][0]; +} + +/* fc=3.5kHz */ +static inline double high_iir(int c, int i, double NewSample) { + double ACoef[NCoef+1] = { + 0.72248704753064896000, + -1.44497409506129790000, + 0.72248704753064896000 + }; + + double BCoef[NCoef+1] = { + 1.00000000000000000000, + -1.36640781670578510000, + 0.52352474706139873000 + }; + static double y[2][2][NCoef+1]; /* output samples */ + static double x[2][2][NCoef+1]; /* input samples */ + int n; + + /* shift the old samples */ + for(n=NCoef; n>0; n--) { + x[c][i][n] = x[c][i][n-1]; + y[c][i][n] = y[c][i][n-1]; + } + + /* Calculate the new output */ + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; + for(n=1; n<=NCoef; n++) + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; + + return y[c][i][0]; +} + +/* fc=3.5kHz */ +static inline double high_cut_iir(int c, int i, double NewSample) { + double ACoef[NCoef+1] = { + 0.03927726802250377400, + 0.07855453604500754700, + 0.03927726802250377400 + }; + + double BCoef[NCoef+1] = { + 1.00000000000000000000, + -1.36640781666419950000, + 0.52352474703279628000 + }; + static double y[2][2][NCoef+1]; /* output samples */ + static double x[2][2][NCoef+1]; /* input samples */ + int n; + + /* shift the old samples */ + for(n=NCoef; n>0; n--) { + x[c][i][n] = x[c][i][n-1]; + y[c][i][n] = y[c][i][n-1]; + } + + /* Calculate the new output */ + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; + for(n=1; n<=NCoef; n++) + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; + + return y[c][i][0]; +} + + +#undef NCoef +#define NCoef 2 + +/* fc=3.2kHz */ +static inline double sb_iir(int c, int i, double NewSample) { + double ACoef[NCoef+1] = { + 0.03356837051492005100, + 0.06713674102984010200, + 0.03356837051492005100 + }; + + double BCoef[NCoef+1] = { + 1.00000000000000000000, + -1.41898265221812010000, + 0.55326988968868285000 + }; + + static double y[2][2][NCoef+1]; /* output samples */ + static double x[2][2][NCoef+1]; /* input samples */ + int n; + + /* shift the old samples */ + for(n=NCoef; n>0; n--) { + x[c][i][n] = x[c][i][n-1]; + y[c][i][n] = y[c][i][n-1]; + } + + /* Calculate the new output */ + x[c][i][0] = NewSample; + y[c][i][0] = ACoef[0] * x[c][i][0]; + for(n=1; n<=NCoef; n++) + y[c][i][0] += ACoef[n] * x[c][i][n] - BCoef[n] * y[c][i][n]; + + return y[c][i][0]; +} + + + +#undef NCoef +#define NCoef 1 #define SB16_NCoef 51 -extern float low_fir_sb16_coef[SB16_NCoef]; +extern double low_fir_sb16_coef[2][SB16_NCoef]; -static inline float low_fir_sb16(int i, float NewSample) +static inline double low_fir_sb16(int c, int i, double NewSample) { - static float x[2][SB16_NCoef+1]; //input samples - static int pos = 0; - float out = 0.0; + static double x[2][2][SB16_NCoef+1]; //input samples + static int pos[2] = { 0, 0 }; + double out = 0.0; int n; /* Calculate the new output */ - x[i][pos] = NewSample; + x[c][i][pos[c]] = NewSample; - for (n = 0; n < ((SB16_NCoef+1)-pos) && n < SB16_NCoef; n++) - out += low_fir_sb16_coef[n] * x[i][n+pos]; + for (n = 0; n < ((SB16_NCoef+1)-pos[c]) && n < SB16_NCoef; n++) + out += low_fir_sb16_coef[c][n] * x[c][i][n+pos[c]]; for (; n < SB16_NCoef; n++) - out += low_fir_sb16_coef[n] * x[i][(n+pos) - (SB16_NCoef+1)]; + out += low_fir_sb16_coef[c][n] * x[c][i][(n+pos[c]) - (SB16_NCoef+1)]; if (i == 1) { - pos++; - if (pos > SB16_NCoef) - pos = 0; + pos[c]++; + if (pos[c] > SB16_NCoef) + pos[c] = 0; } return out; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index bfa35d520..48d4fdd1e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -314,6 +314,7 @@ extern int machine_at_r418_init(const machine_t *); extern int machine_at_ls486e_init(const machine_t *); extern int machine_at_4dps_init(const machine_t *); extern int machine_at_4sa2_init(const machine_t *); +extern int machine_at_m4li_init(const machine_t *); extern int machine_at_alfredo_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *); extern int machine_at_486ap4_init(const machine_t *); @@ -353,6 +354,10 @@ extern int machine_at_excalibur_init(const machine_t *); extern int machine_at_batman_init(const machine_t *); extern int machine_at_ambradp60_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_DELLS4) +extern int machine_at_dellxp60_init(const machine_t *); +extern int machine_at_opti560l_init(const machine_t *); +#endif extern int machine_at_valuepointp60_init(const machine_t *); extern int machine_at_p5mp3_init(const machine_t *); extern int machine_at_pb520r_init(const machine_t *); @@ -478,6 +483,7 @@ extern int machine_at_awo671r_init(const machine_t *); extern int machine_at_63a_init(const machine_t *); extern int machine_at_s370sba_init(const machine_t *); extern int machine_at_apas3_init(const machine_t *); +extern int machine_at_603tcf_init(const machine_t *); /* m_at_misc.c */ extern int machine_at_vpc2007_init(const machine_t *); diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index 2117dcbfb..07b1f3097 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -122,6 +122,7 @@ extern const device_t i440gx_agp_device; extern const device_t via_vp3_agp_device; extern const device_t via_mvp3_agp_device; extern const device_t via_apro_agp_device; +extern const device_t via_vt8601_agp_device; #endif diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index f3180da91..221696acc 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -37,10 +37,10 @@ /* SB 2.0 CD version */ typedef struct sb_ct1335_mixer_t { - int32_t master; - int32_t voice; - int32_t fm; - int32_t cd; + double master; + double voice; + double fm; + double cd; uint8_t index; uint8_t regs[256]; @@ -48,12 +48,12 @@ typedef struct sb_ct1335_mixer_t /* SB PRO */ typedef struct sb_ct1345_mixer_t { - int32_t master_l, master_r; - int32_t voice_l, voice_r; - int32_t fm_l, fm_r; - int32_t cd_l, cd_r; - int32_t line_l, line_r; - int32_t mic; + double master_l, master_r; + double voice_l, voice_r; + double fm_l, fm_r; + double cd_l, cd_r; + double line_l, line_r; + double mic; /*see sb_ct1745_mixer for values for input selector*/ int32_t input_selector; @@ -71,13 +71,13 @@ typedef struct sb_ct1345_mixer_t /* SB16 and AWE32 */ typedef struct sb_ct1745_mixer_t { - int32_t master_l, master_r; - int32_t voice_l, voice_r; - int32_t fm_l, fm_r; - int32_t cd_l, cd_r; - int32_t line_l, line_r; - int32_t mic; - int32_t speaker; + double master_l, master_r; + double voice_l, voice_r; + double fm_l, fm_r; + double cd_l, cd_r; + double line_l, line_r; + double mic; + double speaker; int bass_l, bass_r; int treble_l, treble_r; @@ -103,8 +103,8 @@ typedef struct sb_ct1745_mixer_t int32_t input_gain_L; int32_t input_gain_R; - int32_t output_gain_L; - int32_t output_gain_R; + double output_gain_L; + double output_gain_R; uint8_t index; uint8_t regs[256]; @@ -112,7 +112,7 @@ typedef struct sb_ct1745_mixer_t typedef struct sb_t { - uint8_t opl_enabled; + uint8_t opl_enabled, mixer_enabled; opl_t opl, opl2; sb_dsp_t dsp; union { @@ -133,6 +133,7 @@ extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p); extern void sb_ct1345_mixer_reset(sb_t* sb); extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p); +extern void sbpro_filter_cd_audio(int channel, double *buffer, void *p); extern void sb_close(void *p); extern void sb_speed_changed(void *p); diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index a1fdb4b42..79bc7b5a2 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -46,7 +46,7 @@ extern int sound_card_current; extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \ int len, void *p), void *p); extern void sound_set_cd_audio_filter(void (*filter)(int channel, \ - float *buffer, void *p), void *p); + double *buffer, void *p), void *p); extern int sound_card_available(int card); extern char *sound_card_getname(int card); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index fa4abc57a..3afbdafb2 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -629,6 +629,31 @@ machine_at_r418_init(const machine_t *model) return ret; } +int +machine_at_m4li_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/m4li/M4LI.04S", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + machine_at_sis_85c496_common_init(model); + device_add(&sis_85c496_device); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_pci_device); + + return ret; +} int machine_at_ls486e_init(const machine_t *model) diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 0848e95f8..d313b4385 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -276,7 +276,6 @@ machine_at_63a_init(const machine_t *model) return ret; } - int machine_at_apas3_init(const machine_t *model) { @@ -307,3 +306,56 @@ machine_at_apas3_init(const machine_t *model) return ret; } + +int +machine_at_603tcf_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/603tcf/603tcfA4.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 1, 2, 3, 4); + device_add(&via_vt8601_device); + device_add(&via_vt82c686b_device); + device_add(&via_vt82c686_sio_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 256); + + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000 /* Power */ + }, { /* temperatures */ + 30, /* MB */ + 30, /* JTPWR */ + 30 /* CPU */ + }, { /* voltages */ + 2050, /* VCORE (2.05V by default) */ + 0, /* unused */ + 3300, /* +3.3V */ + RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */ + RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */ + RESISTOR_DIVIDER(12000, 59, 20), /* -12V (divider values bruteforced) */ + RESISTOR_DIVIDER(5000, 1, 2) /* -5V (divider values bruteforced) */ + } + }; + hwm_set_values(machine_hwm); + device_add(&via_vt82c686_hwm_device); + + return ret; +} diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index e79395680..7ef6becad 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -120,6 +120,67 @@ machine_at_batman_init(const machine_t *model) return ret; } +#if defined(DEV_BRANCH) && defined(USE_DELLS4) +int +machine_at_dellxp60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/dellxp60/XP60-A08.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&sio_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + +int +machine_at_opti560l_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/opti560l/560L_A06.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430lx_device); + device_add(&keyboard_ps2_intel_ami_pci_device); + device_add(&sio_device); + device_add(&fdc37c665_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} +#endif int machine_at_ambradp60_init(const machine_t *model) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 151c4c82b..0d1ce9da7 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -774,14 +774,15 @@ machine_at_gw2kte_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&pc87306_device); + device_add(&fdc37c932fr_device); device_add(&intel_flash_bxt_ami_device); return ret; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3fb99806f..55dc4b45b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -244,6 +244,7 @@ const machine_t machines[] = { { "[SiS 496] Lucky Star LS-486E", "ls486e", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_IDE_DUAL, 1, 128, 1, 255, machine_at_ls486e_init, NULL }, { "[SiS 496] Rise Computer R418", "r418", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_IDE_DUAL, 1, 255, 1, 255, machine_at_r418_init, NULL }, { "[SiS 496] Soyo 4SA2", "4sa2", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_IDE_DUAL, 1, 255, 1, 255, machine_at_4sa2_init, NULL }, + { "[SiS 496] Micronics M4Li", "m4li", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 1, 128, 1, 127, machine_at_m4li_init, NULL }, { "[SiS 496] Zida Tomato 4DP", "4dps", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_IDE_DUAL, 1, 255, 1, 255, machine_at_4dps_init, NULL }, #if defined(DEV_BRANCH) && defined(NO_SIO) { "[VIA VT82C496G] FIC VIP-IO2", "486vipio2", MACHINE_TYPE_486, {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCIV | MACHINE_IDE_DUAL, 1, 128, 1, 255, machine_at_486vipio2_init, NULL }, @@ -265,7 +266,11 @@ const machine_t machines[] = { /* 430LX */ { "[i430LX] IBM Ambra DP60 PCI", "ambradp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_ambradp60_init, NULL }, { "[i430LX] IBM PS/ValuePoint P60", "valuepointp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_valuepointp60_init, NULL }, - { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_batman_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_DELLS4) + { "[i430LX] Dell Dimension XPS P60", "dellxp60", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_dellxp60_init, NULL }, + { "[i430LX] Dell OptiPlex 560/L", "opti560l", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_opti560l_init, NULL }, +#endif + { "[i430LX] Intel Premiere/PCI", "revenge", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_batman_init, NULL }, { "[i430LX] ASUS P/I-P5MP3", "p5mp3", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE, 2, 192, 2, 127, machine_at_p5mp3_init, NULL }, { "[i430LX] Micro Star 586MC1", "586mc1", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 2, 128, 2, 127, machine_at_586mc1_init, NULL }, { "[i430LX] Packard Bell PB520R", "pb520r", MACHINE_TYPE_SOCKET4, {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8, 136, 2, 127, machine_at_pb520r_init, at_pb520r_get_device }, @@ -399,6 +404,7 @@ const machine_t machines[] = { /* VIA Apollo Pro */ { "[VIA Apollo Pro] PC Partner APAS3", "apas3", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 768, 8, 255, machine_at_apas3_init, NULL }, + { "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, {{"Intel", cpus_Celeron}, {"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 512, 8, 255, machine_at_603tcf_init, NULL }, /* Miscellaneous/Fake/Hypervisor machines */ { "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, {{"Intel", cpus_PentiumIID}, {"Intel/PGA370", cpus_Celeron},{"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8, 1024, 8, 255, machine_at_vpc2007_init, NULL }, diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 5b9ea8dc6..c04a2d5eb 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -2223,7 +2223,7 @@ pcnet_bcr_readw(nic_t *dev, uint16_t rap) val |= (val & 0x017f & dev->u32Lnkst) ? 0x8000 : 0; break; - case BCR_MIIADDR: + case BCR_MIIMDR: if ((dev->board == DEV_AM79C973) && (((dev->aBCR[BCR_MIIADDR] >> 5) & 0x1f) == 0)) { uint16_t miiaddr = dev->aBCR[BCR_MIIADDR] & 0x1f; val = pcnet_mii_readw(dev, miiaddr); diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 02ae6556e..80161b4be 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -392,6 +392,9 @@ poll_thread(void *arg) slirp_log("SLiRP: polling stopped.\n"); thread_set_event(slirp->poll_state); + /* Destroy event here to avoid a crash. */ + slirp_log("SLiRP: thread ended\n"); + thread_destroy_event(slirp->poll_state); /* Free here instead of immediately freeing the global slirp on the main thread to avoid a race condition. */ slirp_cleanup(slirp->slirp); @@ -451,8 +454,6 @@ net_slirp_close(void) /* Wait for the thread to finish. */ slirp_log("SLiRP: waiting for thread to end...\n"); thread_wait_event(slirp->poll_state, -1); - slirp_log("SLiRP: thread ended\n"); - thread_destroy_event(slirp->poll_state); } /* Shutdown work is done by the thread on its local copy of slirp. */ diff --git a/src/nvr_at.c b/src/nvr_at.c index b2694daf3..039d32eb0 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -515,21 +515,18 @@ timer_intr(void *priv) timer_advance_u64(&local->rtc_timer, RTCCONST); if (local->state == 1) { - local->count--; - if (local->count == 0) + if (--local->count == 0) { timer_load_count(nvr); - else - return; - } else - return; - nvr->regs[RTC_REGC] |= REGC_PF; - if (nvr->regs[RTC_REGB] & REGB_PIE) { - nvr->regs[RTC_REGC] |= REGC_IRQF; + nvr->regs[RTC_REGC] |= REGC_PF; + if (nvr->regs[RTC_REGB] & REGB_PIE) { + nvr->regs[RTC_REGC] |= REGC_IRQF; - /* Generate an interrupt. */ - if (nvr->irq != -1) - picint(1 << nvr->irq); + /* Generate an interrupt. */ + if (nvr->irq != -1) + picint(1 << nvr->irq); + } + } } } diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index ba4b59b6d..b1c94f2bf 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -139,7 +139,7 @@ fdc37c93x_fdc_handler(fdc37c93x_t *dev) fdc_remove(dev->fdc); if (global_enable && local_enable) { - ld_port = make_port(dev, 0); + ld_port = make_port(dev, 0) & 0xFFF8; if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) fdc_set_base(dev->fdc, ld_port); } @@ -159,7 +159,7 @@ fdc37c93x_lpt_handler(fdc37c93x_t *dev) lpt1_remove(); if (global_enable && local_enable) { - ld_port = make_port(dev, 3); + ld_port = make_port(dev, 3) & 0xFFFC; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) lpt1_init(ld_port); } @@ -177,7 +177,7 @@ fdc37c93x_serial_handler(fdc37c93x_t *dev, int uart) serial_remove(dev->uart[uart]); if (global_enable && local_enable) { - ld_port = make_port(dev, uart_no); + ld_port = make_port(dev, uart_no) & 0xFFF8; if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) serial_setup(dev->uart[uart], ld_port, dev->ld_regs[uart_no][0x70]); } @@ -203,7 +203,7 @@ fdc37c93x_nvr_sec_handler(fdc37c93x_t *dev) nvr_at_sec_handler(0, dev->nvr_sec_base, dev->nvr); if (local_enable) { - dev->nvr_sec_base = ld_port = make_port_sec(dev, 6); + dev->nvr_sec_base = ld_port = make_port_sec(dev, 6) & 0xFFFE; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFE)) nvr_at_sec_handler(1, ld_port, dev->nvr); } @@ -335,14 +335,14 @@ fdc37c93x_acpi_handler(fdc37c93x_t *dev) acpi_update_io_mapping(dev->acpi, 0x0000, local_enable); if (local_enable) { - ld_port = make_port(dev, 0x0a); + ld_port = make_port(dev, 0x0a) & 0xFFF0; if ((ld_port >= 0x0100) && (ld_port <= 0x0FF0)) acpi_update_io_mapping(dev->acpi, ld_port, local_enable); } acpi_update_aux_io_mapping(dev->acpi, 0x0000, local_enable); if (local_enable) { - ld_port = make_port_sec(dev, 0x0a); + ld_port = make_port_sec(dev, 0x0a) & 0xFFF8; if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) acpi_update_aux_io_mapping(dev->acpi, ld_port, local_enable); } @@ -789,7 +789,7 @@ static const device_t access_bus_device = { 0, 0x03, access_bus_init, access_bus_close, NULL, - NULL, NULL, NULL, + { NULL }, NULL, NULL, NULL }; diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 726289365..6f2656ff8 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -221,14 +221,14 @@ static void ad1848_poll(void *p) } } -static void ad1848_filter_cd_audio(int channel, float *buffer, void *p) +static void ad1848_filter_cd_audio(int channel, double *buffer, void *p) { ad1848_t *ad1848 = (ad1848_t *)p; int32_t c; uint32_t volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l; c = (((int32_t) *buffer) * volume) >> 16; - *buffer = (float) c; + *buffer = (double) c; } void ad1848_init(ad1848_t *ad1848, int type) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 7cec733a8..a73d34ba5 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -1274,7 +1274,7 @@ static void es1371_get_buffer(int32_t *buffer, int len, void *p) es1371->pos = 0; } -static void es1371_filter_cd_audio(int channel, float *buffer, void *p) +static void es1371_filter_cd_audio(int channel, double *buffer, void *p) { es1371_t *es1371 = (es1371_t *)p; int32_t c; @@ -1284,7 +1284,7 @@ static void es1371_filter_cd_audio(int channel, float *buffer, void *p) c = (((int32_t) *buffer) * cd) >> 15; c = (c * master) >> 15; - *buffer = (float) c; + *buffer = (double) c; } static inline double sinc(double x) diff --git a/src/sound/snd_azt2316a.c b/src/sound/snd_azt2316a.c index b88ee9abb..f129e2e60 100644 --- a/src/sound/snd_azt2316a.c +++ b/src/sound/snd_azt2316a.c @@ -1172,6 +1172,7 @@ azt_init(const device_t *info) azt2316a_create_config_word(azt2316a); sound_add_handler(azt2316a_get_buffer, azt2316a); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, azt2316a->sb); if (azt2316a->cur_mpu401_enabled) { azt2316a->mpu = (mpu_t *) malloc(sizeof(mpu_t)); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 37e09a5e1..b1b71d926 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -37,39 +37,39 @@ #include <86box/filters.h> #include <86box/snd_sb.h> -//#define SB_DSP_RECORD_DEBUG - -#ifdef SB_DSP_RECORD_DEBUG -FILE* soundfsb = 0/*NULL*/; -FILE* soundfsbin = 0/*NULL*/; -#endif - /* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps. Note that for positive dB values, this is not amplitude, it is amplitude-1. */ -const float sb_bass_treble_4bits[]= { - 0.199526231, 0.25, 0.316227766, 0.398107170, 0.5, 0.63095734, 0.794328234, 1, +static const double sb_bass_treble_4bits[]= { + 0.199526231, 0.25, 0.316227766, 0.398107170, 0.5, 0.63095734, 0.794328234, 1, 0, 0.25892541, 0.584893192, 1, 1.511886431, 2.16227766, 3, 4.011872336 }; /* Attenuation tables for the mixer. Max volume = 32767 in order to give 6dB of * headroom and avoid integer overflow */ -const int32_t sb_att_2dbstep_5bits[]= +static const double sb_att_2dbstep_5bits[]= { - 25,32,41,51,65,82,103,130,164,206,260,327,412,519,653, - 822,1036,1304,1641,2067,2602,3276,4125,5192,6537,8230,10362,13044, - 16422,20674,26027,32767 + 25.0, 32.0, 41.0, 51.0, 65.0, 82.0, 103.0, 130.0, 164.0, 206.0, + 260.0, 327.0, 412.0, 519.0, 653.0, 822.0, 1036.0, 1304.0, 1641.0, 2067.0, + 2602.0, 3276.0, 4125.0, 5192.0, 6537.0, 8230.0, 10362.0, 13044.0, 16422.0, 20674.0, + 26027.0, 32767.0 }; -const int32_t sb_att_4dbstep_3bits[]= + +static const double sb_att_4dbstep_3bits[]= { - 164,2067,3276,5193,8230,13045,20675,32767 + 164.0, 2067.0, 3276.0, 5193.0, 8230.0, 13045.0, 20675.0, 32767.0 }; -const int32_t sb_att_7dbstep_2bits[]= + +static const double sb_att_7dbstep_2bits[]= { - 164,6537,14637,32767 + 164.0, 6537.0, 14637.0, 32767.0 }; +static const uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270}; +static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; + + #ifdef ENABLE_SB_LOG int sb_do_log = ENABLE_SB_LOG; @@ -90,707 +90,616 @@ sb_log(const char *fmt, ...) #endif -/* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ -static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) +/* SB 1, 1.5, MCV, and 2 do not have a mixer, so signal is hardwired. */ +static void +sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { - sb_t *sb = (sb_t *)p; - - int c; + sb_t *sb = (sb_t *) p; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + int c; + double out = 0.0; - if (sb->opl_enabled) - opl2_update(&sb->opl); + if (sb->opl_enabled) + opl2_update(&sb->opl); - sb_dsp_update(&sb->dsp); + sb_dsp_update(&sb->dsp); - for (c = 0; c < len * 2; c += 2) - { - int32_t out = 0; - if (sb->opl_enabled) - out = ((sb->opl.buffer[c] * 47000) >> 16); - - //TODO: Recording: Mic and line In with AGC - out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * 65536) / 3) >> 16; - - buffer[c] += out; - buffer[c + 1] += out; - } - - sb->pos = 0; - - if (sb->opl_enabled) - sb->opl.pos = 0; - - sb->dsp.pos = 0; -} - -static void sb2_filter_cd_audio(int channel, float *buffer, void *p) -{ - int32_t c; - - c = (int32_t)(((sb_iir(0, *buffer) / 1.3) * 65536) / 3) >> 16; - *buffer = (float) c; -} - -static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - - int c; - - if (sb->opl_enabled) - opl2_update(&sb->opl); - - sb_dsp_update(&sb->dsp); - - for (c = 0; c < len * 2; c += 2) - { - int32_t out = 0; - - if (sb->opl_enabled) - out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * 47000) >> 15); - - /* 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 */ - out += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice) / 3) >> 15; - - out = (out * mixer->master) >> 15; - - buffer[c] += out; - buffer[c + 1] += out; - } - - sb->pos = 0; - - if (sb->opl_enabled) - sb->opl.pos = 0; - - sb->dsp.pos = 0; -} - -static void sb2_mixer_filter_cd_audio(int channel, float *buffer, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - int32_t c; - - c = (int32_t)(((sb_iir(0, *buffer) / 1.3) * mixer->voice) / 3) >> 15; - c = (c * mixer->master) >> 15; - *buffer = (float) c; -} - -void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - - int c; + for (c = 0; c < len * 2; c += 2) { + out = 0.0; if (sb->opl_enabled) { - if (sb->dsp.sb_type == SBPRO) { - opl2_update(&sb->opl); - opl2_update(&sb->opl2); - } else - opl3_update(&sb->opl); + out = ((double) sb->opl.buffer[c]) * 0.7171630859375; + if (sb->mixer_enabled) + out *= mixer->fm; } - sb_dsp_update(&sb->dsp); + /* 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 += (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice) / 3.9; - for (c = 0; c < len * 2; c += 2) - { - int32_t out_l = 0, out_r = 0; - - if (sb->opl_enabled) { - if (sb->dsp.sb_type == SBPRO) { - /* - * Two chips for LEFT and RIGHT channels. - * Each chip stores data into the LEFT channel - * only (no sample alternating.) - */ - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * 47000) >> 15); - out_r = ((((sb->opl2.buffer[c] * mixer->fm_r) >> 16) * 47000) >> 15); - } else { - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * 47000) >> 15); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * 47000) >> 15); - } - } + out *= mixer->master; + } else + out += (((sb_iir(0, 0, (double) sb->dsp.buffer[c]) / 1.3) * 65536.0) / 3.0) / 65536.0; - /*TODO: Implement the stereo switch on the mixer instead of on the dsp? */ - if (mixer->output_filter) - { - out_l += (int32_t)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 15; - out_r += (int32_t)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 15; - } - else - { - out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15; - out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15; - } - //TODO: recording CD, Mic with AGC or line in. Note: mic volume does not affect recording. - - out_l = (out_l * mixer->master_l) >> 15; - out_r = (out_r * mixer->master_r) >> 15; + buffer[c] += (int32_t) out; + buffer[c + 1] += (int32_t) out; + } - buffer[c] += out_l; - buffer[c + 1] += out_r; - } + sb->pos = 0; - sb->pos = 0; + if (sb->opl_enabled) + sb->opl.pos = 0; + + sb->dsp.pos = 0; +} + + +static void +sb2_filter_cd_audio(int channel, double *buffer, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + double c; + + if (sb->mixer_enabled) { + c = ((sb_iir(1, 0, *buffer) / 1.3) * mixer->cd) / 3.0; + *buffer = c * mixer->master; + } else { + c = (((sb_iir(1, 0, ((double) *buffer)) / 1.3) * 65536) / 3.0) / 65536.0; + *buffer = c; + } +} + + +void +sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + int c; + double out_l = 0.0, out_r = 0.0; + + if (sb->opl_enabled) { + if (sb->dsp.sb_type == SBPRO) { + opl2_update(&sb->opl); + opl2_update(&sb->opl2); + } else + opl3_update(&sb->opl); + } + + sb_dsp_update(&sb->dsp); + + for (c = 0; c < len * 2; c += 2) { + out_l = 0.0, out_r = 0.0; if (sb->opl_enabled) { - sb->opl.pos = 0; - if (sb->dsp.sb_type != SBPRO) - sb->opl2.pos = 0; + if (sb->dsp.sb_type == SBPRO) { + /* Two chips for LEFT and RIGHT channels. + Each chip stores data into the LEFT channel only (no sample alternating.) */ + out_l = (((double) sb->opl.buffer [c ]) * mixer->fm_l) * 0.7171630859375; + out_r = (((double) sb->opl2.buffer[c ]) * mixer->fm_r) * 0.7171630859375; + } else { + out_l = (((double) sb->opl.buffer[c ]) * mixer->fm_l) * 0.7171630859375; + out_r = (((double) sb->opl.buffer[c + 1]) * mixer->fm_r) * 0.7171630859375; + } } - sb->dsp.pos = 0; + /* TODO: Implement the stereo switch on the mixer instead of on the dsp? */ + if (mixer->output_filter) { + out_l += (sb_iir(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.9; + out_r += (sb_iir(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.9; + } else { + out_l += (sb->dsp.buffer[c] * mixer->voice_l) / 3.0; + out_r += (sb->dsp.buffer[c + 1] * mixer->voice_r) / 3.0; + } + /* TODO: recording CD, Mic with AGC or line in. Note: mic volume does not affect recording. */ + + out_l *= mixer->master_l; + out_r *= mixer->master_r; + + buffer[c] += (int32_t) out_l; + buffer[c + 1] += (int32_t) out_r; + } + + sb->pos = 0; + + if (sb->opl_enabled) { + sb->opl.pos = 0; + if (sb->dsp.sb_type != SBPRO) + sb->opl2.pos = 0; + } + + sb->dsp.pos = 0; } -static void sbpro_filter_cd_audio(int channel, float *buffer, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - int32_t c; - int32_t voice = channel ? mixer->voice_r : mixer->voice_l; - int32_t master = channel ? mixer->master_r : mixer->master_l; - if (mixer->output_filter) - c = (int32_t)(((sb_iir(channel, *buffer) / 1.3) * voice) / 3) >> 15; - else - c = ((int32_t)(((int32_t) *buffer) * voice) / 3) >> 15; - c = (c * master) >> 15; - *buffer = (float) c; +void +sbpro_filter_cd_audio(int channel, double *buffer, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + double c; + double cd = channel ? mixer->cd_r : mixer->cd_l; + double master = channel ? mixer->master_r : mixer->master_l; + + if (mixer->output_filter) + c = (sb_iir(1, channel, *buffer) * cd) / 3.9; + else + c = (*buffer * cd) / 3.0; + *buffer = c * master; } -static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) + +static void +sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - int dsp_rec_pos = sb->dsp.record_pos_write; - int c; + sb_t *sb = (sb_t *)p; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + int c, dsp_rec_pos = sb->dsp.record_pos_write; + int c_emu8k, c_record; + int32_t in_l, in_r; + double out_l = 0.0, out_r = 0.0; + double bass_treble; - if (sb->opl_enabled) - opl3_update(&sb->opl); + if (sb->opl_enabled) + opl3_update(&sb->opl); - sb_dsp_update(&sb->dsp); + if (sb->dsp.sb_type > SB16) + emu8k_update(&sb->emu8k); - for (c = 0; c < len * 2; c += 2) - { - int32_t out_l = 0, out_r = 0, in_l, in_r; - - if (sb->opl_enabled) { - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * 47000) >> 15); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * 47000) >> 15); - } + sb_dsp_update(&sb->dsp); - /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ - in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; - in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; - - out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15; - out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15; + for (c = 0; c < len * 2; c += 2) { + out_l = 0.0, out_r = 0.0; - out_l = (out_l * mixer->master_l) >> 15; - out_r = (out_r * mixer->master_r) >> 15; - - if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) - { - /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ - if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]); - if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); - if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); - if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); - if (mixer->bass_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->bass_l])); - if (mixer->bass_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->bass_r])); - if (mixer->treble_l<8) out_l = (int32_t)((out_l )*sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->treble_l])); - if (mixer->treble_r<8) out_r = (int32_t)((out_r )*sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->treble_r])); - } - if (sb->dsp.sb_enable_i) - { - int c_record = dsp_rec_pos; - c_record +=(((c/2) * sb->dsp.sb_freq) / 48000)*2; - in_l <<= mixer->input_gain_L; - in_r <<= mixer->input_gain_R; - // Clip signal - if (in_l < -32768) - in_l = -32768; - else if (in_l > 32767) - in_l = 32767; - - if (in_r < -32768) - in_r = -32768; - else if (in_r > 32767) - in_r = 32767; - sb->dsp.record_buffer[c_record&0xFFFF] = in_l; - sb->dsp.record_buffer[(c_record+1)&0xFFFF] = in_r; - } + if (sb->dsp.sb_type > SB16) + c_emu8k = ((((c / 2) * 44100) / 48000) * 2); - buffer[c] += (out_l << mixer->output_gain_L); - buffer[c + 1] += (out_r << mixer->output_gain_R); - } - sb->dsp.record_pos_write+=((len * sb->dsp.sb_freq) / 48000)*2; - sb->dsp.record_pos_write&=0xFFFF; - - sb->pos = 0; - - if (sb->opl_enabled) - sb->opl.pos = 0; - - sb->dsp.pos = 0; -} -#ifdef SB_DSP_RECORD_DEBUG -int old_dsp_rec_pos=0; -int buf_written=0; -int last_crecord=0; -#endif - -static void sb16_awe32_filter_cd_audio(int channel, float *buffer, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - int32_t c; - int32_t voice = channel ? mixer->voice_r : mixer->voice_l; - int32_t master = channel ? mixer->master_r : mixer->master_l; - int32_t bass = channel ? mixer->bass_r : mixer->bass_l; - int32_t treble = channel ? mixer->treble_r : mixer->treble_l; - int32_t output_gain = channel ? mixer->output_gain_R : mixer->output_gain_L; - - c = ((int32_t)(low_fir_sb16(channel, *buffer) * voice) / 3) >> 15; - c = (c * master) >> 15; - - if (bass != 8 || treble != 8) { - /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ - if (bass>8) c += (int32_t)(low_iir(channel, (float)c)*sb_bass_treble_4bits[bass]); - if (treble>8) c += (int32_t)(high_iir(channel, (float)c)*sb_bass_treble_4bits[treble]); - if (bass<8) c = (int32_t)((c )*sb_bass_treble_4bits[bass] + low_cut_iir(channel, (float)c)*(1.f-sb_bass_treble_4bits[bass])); - if (treble<8) c = (int32_t)((c )*sb_bass_treble_4bits[treble] + high_cut_iir(channel, (float)c)*(1.f-sb_bass_treble_4bits[treble])); + if (sb->opl_enabled) { + out_l = ((double) sb->opl.buffer[c ]) * mixer->fm_l * 0.7171630859375; + out_r = ((double) sb->opl.buffer[c + 1]) * mixer->fm_r * 0.7171630859375; } - *buffer = (float) (c << output_gain); + if (sb->dsp.sb_type > SB16) { + out_l += (((double) sb->emu8k.buffer[c_emu8k]) * mixer->fm_l); + out_r += (((double) sb->emu8k.buffer[c_emu8k + 1]) * mixer->fm_r); + } + + /* TODO: Multi-recording mic with agc/+20db, CD, and line in with channel inversion */ + in_l = (mixer->input_selector_left & INPUT_MIDI_L) ? ((int32_t) out_l) : + 0 + (mixer->input_selector_left & INPUT_MIDI_R) ? ((int32_t) out_r) : 0; + in_r = (mixer->input_selector_right & INPUT_MIDI_L) ? ((int32_t) out_l) : + 0 + (mixer->input_selector_right & INPUT_MIDI_R) ? ((int32_t) out_r) : 0; + + /* We divide by 3 to get the volume down to normal. */ + out_l += (low_fir_sb16(0, 0, (double) sb->dsp.buffer[c]) * mixer->voice_l) / 3.0; + out_r += (low_fir_sb16(0, 1, (double) sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3.0; + + out_l *= mixer->master_l; + out_r *= mixer->master_r; + + /* This is not exactly how one does bass/treble controls, but the end result is like it. + A better implementation would reduce the CPU usage. */ + if (mixer->bass_l != 8) { + bass_treble = sb_bass_treble_4bits[mixer->bass_l]; + + if (mixer->bass_l > 8) + out_l += (low_iir(0, 0, out_l) * bass_treble); + else if (mixer->bass_l < 8) + out_l = ((out_l) * bass_treble + low_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + } + + if (mixer->bass_r != 8) { + bass_treble = sb_bass_treble_4bits[mixer->bass_r]; + + if (mixer->bass_r > 8) + out_r += (low_iir(0, 1, out_r) * bass_treble); + else if (mixer->bass_r < 8) + out_r = ((out_r) * bass_treble + low_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + + if (mixer->treble_l != 8) { + bass_treble = sb_bass_treble_4bits[mixer->treble_l]; + + if (mixer->treble_l > 8) + out_l += (high_iir(0, 0, out_l) * bass_treble); + else if (mixer->treble_l < 8) + out_l = ((out_l) * bass_treble + high_cut_iir(0, 0, out_l) * (1.0 - bass_treble)); + } + + if (mixer->treble_r != 8) { + bass_treble = sb_bass_treble_4bits[mixer->treble_r]; + + if (mixer->treble_r > 8) + out_r += (high_iir(0, 1, out_r) * bass_treble); + else if (mixer->treble_r < 8) + out_r = ((out_l) * bass_treble + high_cut_iir(0, 1, out_r) * (1.0 - bass_treble)); + } + + if (sb->dsp.sb_enable_i) { + c_record = dsp_rec_pos + ((c * sb->dsp.sb_freq) / 48000); + in_l <<= mixer->input_gain_L; + in_r <<= mixer->input_gain_R; + + /* Clip signal */ + if (in_l < -32768) + in_l = -32768; + else if (in_l > 32767) + in_l = 32767; + + if (in_r < -32768) + in_r = -32768; + else if (in_r > 32767) + in_r = 32767; + + sb->dsp.record_buffer[c_record & 0xffff] = in_l; + sb->dsp.record_buffer[(c_record+1) & 0xffff] = in_r; + } + + buffer[c] += (int32_t) (out_l * mixer->output_gain_L); + buffer[c + 1] += (int32_t) (out_r * mixer->output_gain_R); + } + + sb->dsp.record_pos_write += ((len * sb->dsp.sb_freq) / 24000); + sb->dsp.record_pos_write &= 0xffff; + + sb->pos = 0; + + if (sb->opl_enabled) + sb->opl.pos = 0; + + sb->dsp.pos = 0; + + if (sb->dsp.sb_type > SB16) + sb->emu8k.pos = 0; } -static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) + +static void +sb16_awe32_filter_cd_audio(int channel, double *buffer, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - int c; - int dsp_rec_pos = sb->dsp.record_pos_write; + sb_t *sb = (sb_t *)p; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + double c; + double cd = channel ? mixer->cd_r : mixer->cd_l /* / 3.0 */; + double master = channel ? mixer->master_r : mixer->master_l; + int32_t bass = channel ? mixer->bass_r : mixer->bass_l; + int32_t treble = channel ? mixer->treble_r : mixer->treble_l; + double bass_treble; + double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L); - if (sb->opl_enabled) - opl3_update(&sb->opl); + c = (low_fir_sb16(1, channel, *buffer) * cd) / 3.0; + c *= master; - emu8k_update(&sb->emu8k); + /* This is not exactly how one does bass/treble controls, but the end result is like it. + A better implementation would reduce the CPU usage. */ + if (bass != 8) { + bass_treble = sb_bass_treble_4bits[bass]; - sb_dsp_update(&sb->dsp); + if (bass > 8) + c += (low_iir(1, channel, c) * bass_treble); + else if (bass < 8) + c = (c * bass_treble + low_cut_iir(1, channel, c) * (1.0 - bass_treble)); + } - for (c = 0; c < len * 2; c += 2) - { - int32_t out_l = 0, out_r = 0, in_l, in_r; - int c_emu8k = (((c/2) * 44100) / 48000)*2; - - if (sb->opl_enabled) { - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 15) * 47000) >> 16); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 15) * 47000) >> 16); + if (treble != 8) { + bass_treble = sb_bass_treble_4bits[treble]; + + if (treble > 8) + c += (high_iir(1, channel, c) * bass_treble); + else if (treble < 8) + c = (c * bass_treble + high_cut_iir(1, channel, c) * (1.0 - bass_treble)); + } + + *buffer = c * output_gain; +} + + +void +sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) +{ + sb_t *sb = (sb_t *)p; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; + + if (!(addr & 1)) { + mixer->index = val; + mixer->regs[0x01] = val; + } else { + if (mixer->index == 0) { + /* Reset */ + mixer->regs[0x02] = mixer->regs[0x06] = 0x08; + mixer->regs[0x08] = 0x00; + /* Changed default from -46dB to 0dB*/ + mixer->regs[0x0a] = 0x06; + } else { + mixer->regs[mixer->index] = val; + switch (mixer->index) { + case 0x00: case 0x02: case 0x06: case 0x08: case 0x0a: + break; + + default: + sb_log("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; } + } - out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 15); - out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_r) >> 15); - - /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ - in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; - in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; - - out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15; - out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15; - - out_l = (out_l * mixer->master_l) >> 15; - out_r = (out_r * mixer->master_r) >> 15; - - if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8) - { - /* This is not exactly how one does bass/treble controls, but the end result is like it. A better implementation would reduce the cpu usage */ - if (mixer->bass_l>8) out_l += (int32_t)(low_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->bass_l]); - if (mixer->bass_r>8) out_r += (int32_t)(low_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->bass_r]); - if (mixer->treble_l>8) out_l += (int32_t)(high_iir(0, (float)out_l)*sb_bass_treble_4bits[mixer->treble_l]); - if (mixer->treble_r>8) out_r += (int32_t)(high_iir(1, (float)out_r)*sb_bass_treble_4bits[mixer->treble_r]); - if (mixer->bass_l<8) out_l = (int32_t)(out_l *sb_bass_treble_4bits[mixer->bass_l] + low_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->bass_l])); - if (mixer->bass_r<8) out_r = (int32_t)(out_r *sb_bass_treble_4bits[mixer->bass_r] + low_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->bass_r])); - if (mixer->treble_l<8) out_l = (int32_t)(out_l *sb_bass_treble_4bits[mixer->treble_l] + high_cut_iir(0, (float)out_l)*(1.f-sb_bass_treble_4bits[mixer->treble_l])); - if (mixer->treble_r<8) out_r = (int32_t)(out_r *sb_bass_treble_4bits[mixer->treble_r] + high_cut_iir(1, (float)out_r)*(1.f-sb_bass_treble_4bits[mixer->treble_r])); - } - if (sb->dsp.sb_enable_i) - { -// in_l += (mixer->input_selector_left&INPUT_CD_L) ? audio_cd_buffer[cd_read_pos+c_emu8k] : 0 + (mixer->input_selector_left&INPUT_CD_R) ? audio_cd_buffer[cd_read_pos+c_emu8k+1] : 0; -// in_r += (mixer->input_selector_right&INPUT_CD_L) ? audio_cd_buffer[cd_read_pos+c_emu8k]: 0 + (mixer->input_selector_right&INPUT_CD_R) ? audio_cd_buffer[cd_read_pos+c_emu8k+1] : 0; - - int c_record = dsp_rec_pos; - c_record +=(((c/2) * sb->dsp.sb_freq) / 48000)*2; - #ifdef SB_DSP_RECORD_DEBUG - if (c_record > 0xFFFF && !buf_written) - { - if (!soundfsb) soundfsb=plat_fopen(L"sound_sb.pcm",L"wb"); - fwrite(sb->dsp.record_buffer,2,0x10000,soundfsb); - old_dsp_rec_pos = dsp_rec_pos; - buf_written=1; - } - #endif - in_l <<= mixer->input_gain_L; - in_r <<= mixer->input_gain_R; - // Clip signal - if (in_l < -32768) - in_l = -32768; - else if (in_l > 32767) - in_l = 32767; - - if (in_r < -32768) - in_r = -32768; - else if (in_r > 32767) - in_r = 32767; - sb->dsp.record_buffer[c_record&0xFFFF] = in_l; - sb->dsp.record_buffer[(c_record+1)&0xFFFF] = in_r; - #ifdef SB_DSP_RECORD_DEBUG - if (c_record != last_crecord) - { - if (!soundfsbin) soundfsbin=plat_fopen(L"sound_sb_in.pcm",L"wb"); - fwrite(&sb->dsp.record_buffer[c_record&0xFFFF],2,2,soundfsbin); - last_crecord=c_record; - } - #endif - } - - buffer[c] += (out_l << mixer->output_gain_L); - buffer[c + 1] += (out_r << mixer->output_gain_R); - } - #ifdef SB_DSP_RECORD_DEBUG - if (old_dsp_rec_pos > dsp_rec_pos) - { - buf_written=0; - old_dsp_rec_pos=dsp_rec_pos; - } - #endif - - sb->dsp.record_pos_write+=((len * sb->dsp.sb_freq) / 48000)*2; - sb->dsp.record_pos_write&=0xFFFF; - - sb->pos = 0; - - if (sb->opl_enabled) - sb->opl.pos = 0; - - sb->dsp.pos = 0; - - sb->emu8k.pos = 0; + mixer->master = sb_att_4dbstep_3bits[(mixer->regs[0x02] >> 1) & 0x7] / 32768.0; + mixer->fm = sb_att_4dbstep_3bits[(mixer->regs[0x06] >> 1) & 0x7] / 32768.0; + mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1) & 0x7] / 32768.0; + mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; + } } -void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) +uint8_t +sb_ct1335_mixer_read(uint16_t addr, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - - if (!(addr & 1)) - { - mixer->index = val; - mixer->regs[0x01] = val; - } - else - { - if (mixer->index == 0) - { - /* Reset */ - mixer->regs[0x02] = 4 << 1; - mixer->regs[0x06] = 4 << 1; - mixer->regs[0x08] = 0 << 1; - /* changed default from -46dB to 0dB*/ - mixer->regs[0x0A] = 3 << 1; - } - else - { - mixer->regs[mixer->index] = val; - switch (mixer->index) - { - case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: - break; + sb_t *sb = (sb_t *)p; + sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - default: - sb_log("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - } - mixer->master = sb_att_4dbstep_3bits[(mixer->regs[0x02] >> 1)&0x7]; - mixer->fm = sb_att_4dbstep_3bits[(mixer->regs[0x06] >> 1)&0x7]; - mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1)&0x7]; - mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0A] >> 1)&0x3]; - } + if (!(addr & 1)) + return mixer->index; + + switch (mixer->index) { + case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: + return mixer->regs[mixer->index]; + default: + sb_log("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + + return 0xff; } -uint8_t sb_ct1335_mixer_read(uint16_t addr, void *p) + +void +sb_ct1335_mixer_reset(sb_t* sb) { - sb_t *sb = (sb_t *)p; - sb_ct1335_mixer_t *mixer = &sb->mixer_sb2; - - if (!(addr & 1)) - return mixer->index; - - switch (mixer->index) - { - case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: - return mixer->regs[mixer->index]; - default: - sb_log("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - - return 0xff; + sb_ct1335_mixer_write(0x254, 0, sb); + sb_ct1335_mixer_write(0x255, 0, sb); } -void sb_ct1335_mixer_reset(sb_t* sb) + +void +sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) { - sb_ct1335_mixer_write(0x254,0,sb); - sb_ct1335_mixer_write(0x255,0,sb); + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; + + if (!(addr & 1)) { + mixer->index = val; + mixer->regs[0x01] = val; + } else { + if (mixer->index == 0) { + /* Reset */ + mixer->regs[0x0a] = mixer->regs[0x0c] = 0x00; + mixer->regs[0x0e] = 0x00; + /* Changed default from -11dB to 0dB */ + mixer->regs[0x04] = mixer->regs[0x22] = 0xee; + mixer->regs[0x26] = mixer->regs[0x28] = 0xee; + mixer->regs[0x2e] = 0x00; + sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0e] & 2); + } else { + mixer->regs[mixer->index] = val; + + switch (mixer->index) { + /* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */ + case 0x02: case 0x06: case 0x08: + mixer->regs[mixer->index + 0x20] = ((val & 0xe) << 4) | (val&0xe); + break; + + case 0x22: case 0x26: case 0x28: + mixer->regs[mixer->index - 0x20] = (val & 0xe); + break; + + /* More compatibility: + SoundBlaster Pro selects register 020h for 030h, 022h for 032h, + 026h for 036h, and 028h for 038h. */ + case 0x30: case 0x32: case 0x36: case 0x38: + mixer->regs[mixer->index - 0x10] = (val & 0xee); + break; + + case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: + case 0x2e: + break; + + default: + sb_log("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + } + + mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5) & 0x7] / 32768.0; + mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1) & 0x7] / 32768.0; + mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5) & 0x7] / 32768.0; + mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1) & 0x7] / 32768.0; + mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5) & 0x7] / 32768.0; + mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1) & 0x7] / 32768.0; + mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5) & 0x7] / 32768.0; + mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1) & 0x7] / 32768.0; + mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 5) & 0x7] / 32768.0; + mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 1) & 0x7] / 32768.0; + + mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0; + + mixer->output_filter = !(mixer->regs[0xe] & 0x20); + mixer->input_filter = !(mixer->regs[0xc] & 0x20); + mixer->in_filter_freq = ((mixer->regs[0xc] & 0x8) == 0) ? 3200 : 8800; + mixer->stereo = mixer->regs[0xe] & 2; + if (mixer->index == 0xe) + sb_dsp_set_stereo(&sb->dsp, val & 2); + + switch ((mixer->regs[0xc] & 6)) { + case 2: + mixer->input_selector = INPUT_CD_L | INPUT_CD_R; + break; + case 6: + mixer->input_selector = INPUT_LINE_L | INPUT_LINE_R; + break; + default: + mixer->input_selector = INPUT_MIC; + break; + } + + /* TODO: pcspeaker volume? Or is it not worth? */ + } } -void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) + +uint8_t +sb_ct1345_mixer_read(uint16_t addr, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - - if (!(addr & 1)) - { - mixer->index = val; - mixer->regs[0x01] = val; - } - else - { - if (mixer->index == 0) - { - /* Reset */ - mixer->regs[0x0A] = 0 << 1; - mixer->regs[0x0C] = (0 << 5) | (0 << 3) | (0 << 1); - mixer->regs[0x0E] = (0 << 5) | (0 << 1); - /* changed default from -11dB to 0dB */ - mixer->regs[0x04] = (7 << 5) | (7 << 1); - mixer->regs[0x22] = (7 << 5) | (7 << 1); - mixer->regs[0x26] = (7 << 5) | (7 << 1); - mixer->regs[0x28] = (7 << 5) | (7 << 1); - mixer->regs[0x2E] = (0 << 5) | (0 << 1); - sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0E] & 2); - } - else - { - mixer->regs[mixer->index] = val; - switch (mixer->index) - { - /* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */ - case 0x02: case 0x06: case 0x08: - mixer->regs[mixer->index+0x20]=((val&0xE) << 4)|(val&0xE); - break; - - case 0x22: case 0x26: case 0x28: - mixer->regs[mixer->index-0x20]=(val&0xE); - break; - - /* More compatibility: SoundBlaster Pro selects register 020h for 030h, 022h for 032h, 026h for 036h,028h for 038h. */ - case 0x30: case 0x32: case 0x36: case 0x38: - mixer->regs[mixer->index-0x10]=(val&0xEE); - break; + sb_t *sb = (sb_t *)p; + sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: - case 0x2e: - break; - - - default: - sb_log("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - } - - mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5)&0x7]; - mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1)&0x7]; - mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5)&0x7]; - mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1)&0x7]; - mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5)&0x7]; - mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1)&0x7]; - mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5)&0x7]; - mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1)&0x7]; - mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2E] >> 5)&0x7]; - mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2E] >> 1)&0x7]; + if (!(addr & 1)) + return mixer->index; - mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0A] >> 1)&0x3]; + switch (mixer->index) { + case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: + case 0x22: case 0x26: case 0x28: case 0x2e: case 0x02: case 0x06: + case 0x30: case 0x32: case 0x36: case 0x38: + return mixer->regs[mixer->index]; - mixer->output_filter = !(mixer->regs[0xE] & 0x20); - mixer->input_filter = !(mixer->regs[0xC] & 0x20); - mixer->in_filter_freq = ((mixer->regs[0xC] & 0x8) == 0) ? 3200 : 8800; - mixer->stereo = mixer->regs[0xE] & 2; - if (mixer->index == 0xE) - sb_dsp_set_stereo(&sb->dsp, val & 2); + default: + sb_log("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } - switch ((mixer->regs[0xc]&6)) - { - case 2: - mixer->input_selector = INPUT_CD_L|INPUT_CD_R; - break; - case 6: - mixer->input_selector = INPUT_LINE_L|INPUT_LINE_R; - break; - default: - mixer->input_selector = INPUT_MIC; - break; - } - - /* TODO: pcspeaker volume? Or is it not worth? */ - } + return 0xff; } -uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p) -{ - sb_t *sb = (sb_t *)p; - sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro; - if (!(addr & 1)) - return mixer->index; - - switch (mixer->index) - { - case 0x00: case 0x04: case 0x0a: case 0x0c: case 0x0e: - case 0x22: case 0x26: case 0x28: case 0x2e: case 0x02: case 0x06: - case 0x30: case 0x32: case 0x36: case 0x38: - return mixer->regs[mixer->index]; - - default: - sb_log("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - - return 0xff; -} -void sb_ct1345_mixer_reset(sb_t* sb) +void +sb_ct1345_mixer_reset(sb_t* sb) { - sb_ct1345_mixer_write(4,0,sb); - sb_ct1345_mixer_write(5,0,sb); + sb_ct1345_mixer_write(4, 0, sb); + sb_ct1345_mixer_write(5, 0, sb); } -void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) + +static void +sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - - if (!(addr & 1)) - mixer->index = val; - else - { - // TODO: and this? 001h: - /*DESCRIPTION - Contains previously selected register value. Mixer Data Register value - NOTES - * SoundBlaster 16 sets bit 7 if previous mixer index invalid. - * Status bytes initially 080h on startup for all but level bytes (SB16) - */ - - if (mixer->index == 0) - { - /* Reset */ - /* Changed defaults from -14dB to 0dB*/ - mixer->regs[0x30]=31 << 3; - mixer->regs[0x31]=31 << 3; - mixer->regs[0x32]=31 << 3; - mixer->regs[0x33]=31 << 3; - mixer->regs[0x34]=31 << 3; - mixer->regs[0x35]=31 << 3; - mixer->regs[0x36]=31 << 3; - mixer->regs[0x37]=31 << 3; - mixer->regs[0x38]=0 << 3; - mixer->regs[0x39]=0 << 3; + sb_t *sb = (sb_t *) p; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - mixer->regs[0x3A]=0 << 3; + if (!(addr & 1)) + mixer->index = val; + else { + /* DESCRIPTION: + Contains previously selected register value. Mixer Data Register value. + NOTES: + SoundBlaster 16 sets bit 7 if previous mixer index invalid. + Status bytes initially 080h on startup for all but level bytes (SB16). */ - mixer->regs[0x3B]=0 << 6; - mixer->regs[0x3C] = OUTPUT_MIC|OUTPUT_CD_R|OUTPUT_CD_L|OUTPUT_LINE_R|OUTPUT_LINE_L; - mixer->regs[0x3D] = INPUT_MIC|INPUT_CD_L|INPUT_LINE_L|INPUT_MIDI_L; - mixer->regs[0x3E] = INPUT_MIC|INPUT_CD_R|INPUT_LINE_R|INPUT_MIDI_R; - - mixer->regs[0x3F] = mixer->regs[0x40] = 0 << 6; - mixer->regs[0x41] = mixer->regs[0x42] = 0 << 6; + if (mixer->index == 0) { + /* Reset: Changed defaults from -14dB to 0dB */ - mixer->regs[0x44] = mixer->regs[0x45] = 8 << 4; - mixer->regs[0x46] = mixer->regs[0x47] = 8 << 4; - - mixer->regs[0x43] = 0; + mixer->regs[0x30] = mixer->regs[0x31] = 0xf8; + mixer->regs[0x32] = mixer->regs[0x33] = 0xf8; + mixer->regs[0x34] = mixer->regs[0x35] = 0xf8; + mixer->regs[0x36] = mixer->regs[0x37] = 0xf8; + mixer->regs[0x38] = mixer->regs[0x39] = 0x00; - mixer->regs[0x83] = 0xff; - sb->dsp.sb_irqm8 = 0; - sb->dsp.sb_irqm16 = 0; - sb->dsp.sb_irqm401 = 0; - } - else - { - mixer->regs[mixer->index] = val; - } - switch (mixer->index) - { - /* SB1/2 compatibility? */ - case 0x02: - mixer->regs[0x30] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; - mixer->regs[0x31] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; - break; - case 0x06: - mixer->regs[0x34] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; - mixer->regs[0x35] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; - break; - case 0x08: - mixer->regs[0x36] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; - mixer->regs[0x37] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; - break; - /* SBPro compatibility. Copy values to sb16 registers. */ - case 0x22: - mixer->regs[0x30] = (mixer->regs[0x22] & 0xF0) | 0x8; - mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) << 4) | 0x8; - break; - case 0x04: - mixer->regs[0x32] = (mixer->regs[0x04] & 0xF0) | 0x8; - mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) << 4) | 0x8; - break; - case 0x26: - mixer->regs[0x34] = (mixer->regs[0x26] & 0xF0) | 0x8; - mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) << 4) | 0x8; - break; - case 0x28: - mixer->regs[0x36] = (mixer->regs[0x28] & 0xF0) | 0x8; - mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; - break; - case 0x0A: - // mixer->regs[0x3A] = (mixer->regs[0x0A]*3)+10; - mixer->regs[0x3A] = (mixer->regs[0x0A] << 5) | 0x18; - break; - case 0x2E: - mixer->regs[0x38] = (mixer->regs[0x2E] & 0xF0) | 0x8; - mixer->regs[0x39] = ((mixer->regs[0x2E] & 0xf) << 4) | 0x8; + mixer->regs[0x3a] = mixer->regs[0x3b] = 0x00; + + mixer->regs[0x3c] = (OUTPUT_MIC | OUTPUT_CD_R | OUTPUT_CD_L | OUTPUT_LINE_R | OUTPUT_LINE_L); + mixer->regs[0x3d] = (INPUT_MIC | INPUT_CD_L | INPUT_LINE_L | INPUT_MIDI_L); + mixer->regs[0x3e] = (INPUT_MIC | INPUT_CD_R | INPUT_LINE_R | INPUT_MIDI_R); + + mixer->regs[0x3f] = mixer->regs[0x40] = 0x00; + mixer->regs[0x41] = mixer->regs[0x42] = 0x00; + + mixer->regs[0x44] = mixer->regs[0x45] = 0x80; + mixer->regs[0x46] = mixer->regs[0x47] = 0x80; + + mixer->regs[0x43] = 0x00; + + mixer->regs[0x83] = 0xff; + sb->dsp.sb_irqm8 = 0; + sb->dsp.sb_irqm16 = 0; + sb->dsp.sb_irqm401 = 0; + } else + mixer->regs[mixer->index] = val; + + switch (mixer->index) { + /* SB1/2 compatibility? */ + case 0x02: + mixer->regs[0x30] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + break; + case 0x06: + mixer->regs[0x34] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + break; + case 0x08: + mixer->regs[0x36] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + break; + /* SBPro compatibility. Copy values to sb16 registers. */ + case 0x22: + mixer->regs[0x30] = (mixer->regs[0x22] & 0xf0) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x22] & 0xf) << 4) | 0x8; + break; + case 0x04: + mixer->regs[0x32] = (mixer->regs[0x04] & 0xf0) | 0x8; + mixer->regs[0x33] = ((mixer->regs[0x04] & 0xf) << 4) | 0x8; + break; + case 0x26: + mixer->regs[0x34] = (mixer->regs[0x26] & 0xf0) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x26] & 0xf) << 4) | 0x8; + break; + case 0x28: + mixer->regs[0x36] = (mixer->regs[0x28] & 0xf0) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; + break; + case 0x0A: + mixer->regs[0x3a] = (mixer->regs[0x0a] << 5) | 0x18; + break; + case 0x2e: + mixer->regs[0x38] = (mixer->regs[0x2e] & 0xf0) | 0x8; + mixer->regs[0x39] = ((mixer->regs[0x2e] & 0xf) << 4) | 0x8; break; - /* - (DSP 4.xx feature) The Interrupt Setup register, addressed as register 80h on the Mixer register map, is used to configure or determine the Interrupt request line. The DMA setup register, addressed as register 81h on the Mixer register map, is used to configure or determine the DMA channels. - - Note: Registers 80h and 81h are Read-only for PnP boards. - */ - case 0x80: - if (val & 1) sb_dsp_setirq(&sb->dsp,2); - if (val & 2) sb_dsp_setirq(&sb->dsp,5); - if (val & 4) sb_dsp_setirq(&sb->dsp,7); - if (val & 8) sb_dsp_setirq(&sb->dsp,10); - break; + /* (DSP 4.xx feature): + The Interrupt Setup register, addressed as register 80h on the Mixer register map, + is used to configure or determine the Interrupt request line. + The DMA setup register, addressed as register 81h on the Mixer register map, is + used to configure or determine the DMA channels. - case 0x81: - /* The documentation is confusing. sounds as if multple dma8 channels could be set. */ - if (val & 1) sb_dsp_setdma8(&sb->dsp,0); - if (val & 2) sb_dsp_setdma8(&sb->dsp,1); - if (val & 8) sb_dsp_setdma8(&sb->dsp,3); - if (val & 0x20) sb_dsp_setdma16(&sb->dsp,5); - if (val & 0x40) sb_dsp_setdma16(&sb->dsp,6); - if (val & 0x80) sb_dsp_setdma16(&sb->dsp,7); - break; + Note: Registers 80h and 81h are Read-only for PnP boards. */ + case 0x80: + if (val & 0x01) + sb_dsp_setirq(&sb->dsp, 2); + if (val & 0x02) + sb_dsp_setirq(&sb->dsp, 5); + if (val & 0x04) + sb_dsp_setirq(&sb->dsp, 7); + if (val & 0x08) + sb_dsp_setirq(&sb->dsp, 10); + break; - case 0x83: + case 0x81: + /* The documentation is confusing. sounds as if multple dma8 channels could + be set. */ + if (val & 0x01) + sb_dsp_setdma8(&sb->dsp, 0); + if (val & 0x02) + sb_dsp_setdma8(&sb->dsp, 1); + if (val & 0x08) + sb_dsp_setdma8(&sb->dsp, 3); + if (val & 0x20) + sb_dsp_setdma16(&sb->dsp, 5); + if (val & 0x40) + sb_dsp_setdma16(&sb->dsp, 6); + if (val & 0x80) + sb_dsp_setdma16(&sb->dsp, 7); + break; + + case 0x83: /* Interrupt mask. */ sb->dsp.sb_irqm8 = !(val & 0x01); sb->dsp.sb_irqm16 = !(val & 0x02); @@ -798,7 +707,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) sb_update_irq(&sb->dsp); break; - case 0x84: + case 0x84: /* MPU Control register, per the Linux source code. */ if (sb->mpu != NULL) { if ((val & 0x06) == 0x00) @@ -809,438 +718,487 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) mpu401_change_addr(sb->mpu, 0); } break; - } + } - mixer->output_selector = mixer->regs[0x3C]; - mixer->input_selector_left = mixer->regs[0x3D]; - mixer->input_selector_right = mixer->regs[0x3E]; + mixer->output_selector = mixer->regs[0x3c]; + mixer->input_selector_left = mixer->regs[0x3d]; + mixer->input_selector_right = mixer->regs[0x3e]; - mixer->master_l = sb_att_2dbstep_5bits[mixer->regs[0x30] >> 3]; - mixer->master_r = sb_att_2dbstep_5bits[mixer->regs[0x31] >> 3]; - mixer->voice_l = sb_att_2dbstep_5bits[mixer->regs[0x32] >> 3]; - mixer->voice_r = sb_att_2dbstep_5bits[mixer->regs[0x33] >> 3]; - mixer->fm_l = sb_att_2dbstep_5bits[mixer->regs[0x34] >> 3]; - mixer->fm_r = sb_att_2dbstep_5bits[mixer->regs[0x35] >> 3]; - mixer->cd_l = (mixer->output_selector&OUTPUT_CD_L) ? sb_att_2dbstep_5bits[mixer->regs[0x36] >> 3] : 0; - mixer->cd_r = (mixer->output_selector&OUTPUT_CD_R) ? sb_att_2dbstep_5bits[mixer->regs[0x37] >> 3] : 0; - mixer->line_l = (mixer->output_selector&OUTPUT_LINE_L) ? sb_att_2dbstep_5bits[mixer->regs[0x38] >> 3] : 0; - mixer->line_r = (mixer->output_selector&OUTPUT_LINE_R) ? sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] : 0; + mixer->master_l = sb_att_2dbstep_5bits[mixer->regs[0x30] >> 3] / 32768.0; + mixer->master_r = sb_att_2dbstep_5bits[mixer->regs[0x31] >> 3] / 32768.0; + mixer->voice_l = sb_att_2dbstep_5bits[mixer->regs[0x32] >> 3] / 32768.0; + mixer->voice_r = sb_att_2dbstep_5bits[mixer->regs[0x33] >> 3] / 32768.0; + mixer->fm_l = sb_att_2dbstep_5bits[mixer->regs[0x34] >> 3] / 32768.0; + mixer->fm_r = sb_att_2dbstep_5bits[mixer->regs[0x35] >> 3] / 32768.0; + mixer->cd_l = (mixer->output_selector & OUTPUT_CD_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x36] >> 3] / 32768.0): 0.0; + mixer->cd_r = (mixer->output_selector & OUTPUT_CD_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x37] >> 3] / 32768.0) : 0.0; + mixer->line_l = (mixer->output_selector & OUTPUT_LINE_L) ? (sb_att_2dbstep_5bits[mixer->regs[0x38] >> 3] / 32768.0) : 0.0; + mixer->line_r = (mixer->output_selector & OUTPUT_LINE_R) ? (sb_att_2dbstep_5bits[mixer->regs[0x39] >> 3] / 32768.0) : 0.0; - mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3A] >> 3]; - mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3B]*3 + 22]; - + mixer->mic = sb_att_2dbstep_5bits[mixer->regs[0x3a] >> 3] / 32768.0; + mixer->speaker = sb_att_2dbstep_5bits[mixer->regs[0x3b] * 3 + 22] / 32768.0; - mixer->input_gain_L = (mixer->regs[0x3F] >> 6); - mixer->input_gain_R = (mixer->regs[0x40] >> 6); - mixer->output_gain_L = (mixer->regs[0x41] >> 6); - mixer->output_gain_R = (mixer->regs[0x42] >> 6); + mixer->input_gain_L = (mixer->regs[0x3f] >> 6); + mixer->input_gain_R = (mixer->regs[0x40] >> 6); + mixer->output_gain_L = (double) (1 << (mixer->regs[0x41] >> 6)); + mixer->output_gain_R = (double) (1 << (mixer->regs[0x42] >> 6)); - mixer->bass_l = mixer->regs[0x46] >> 4; - mixer->bass_r = mixer->regs[0x47] >> 4; - mixer->treble_l = mixer->regs[0x44] >> 4; - mixer->treble_r = mixer->regs[0x45] >> 4; + mixer->bass_l = mixer->regs[0x46] >> 4; + mixer->bass_r = mixer->regs[0x47] >> 4; + mixer->treble_l = mixer->regs[0x44] >> 4; + mixer->treble_r = mixer->regs[0x45] >> 4; - /*TODO: pcspeaker volume, with "output_selector" check? or better not? */ - sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - } + /* TODO: PC Speaker volume, with "output_selector" check? or better not? */ + sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + } } -uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) + +static uint8_t +sb_ct1745_mixer_read(uint16_t addr, void *p) { - sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - uint8_t temp, ret = 0xff; + sb_t *sb = (sb_t *) p; + sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + uint8_t temp, ret = 0xff; - if (!(addr & 1)) - ret = mixer->index; + if (!(addr & 1)) + ret = mixer->index; - sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - if (mixer->index>=0x30 && mixer->index<=0x47) + if ((mixer->index >= 0x30) && (mixer->index <= 0x47)) + ret = mixer->regs[mixer->index]; + else switch (mixer->index) { + case 0x00: ret = mixer->regs[mixer->index]; - else switch (mixer->index) { - case 0x00: - ret = mixer->regs[mixer->index]; - break; + break; - /*SB Pro compatibility*/ - case 0x04: - ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); - break; - case 0x0a: - // ret = (mixer->regs[0x3a] - 10) / 3; - ret = (mixer->regs[0x3a] >> 5); - break; - case 0x02: - ret = ((mixer->regs[0x30] >> 4) & 0x0f); - break; - case 0x06: - ret = ((mixer->regs[0x34] >> 4) & 0x0f); - break; - case 0x08: - ret = ((mixer->regs[0x36] >> 4) & 0x0f); - break; - case 0x0e: - ret = 0x02; - break; - case 0x22: - ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); - break; - case 0x26: - ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); - break; - case 0x28: - ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); - break; - case 0x2e: - ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); - break; - - case 0x48: - // Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector). even when writing. - // Also, the version I have (5.17) does not use the MIDI.L/R input selectors. it uses the volume to mute (Affecting the output, obviously) - ret = mixer->regs[mixer->index]; - break; + /*SB Pro compatibility*/ + case 0x04: + ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); + break; + case 0x0a: + ret = (mixer->regs[0x3a] >> 5); + break; + case 0x02: + ret = ((mixer->regs[0x30] >> 4) & 0x0f); + break; + case 0x06: + ret = ((mixer->regs[0x34] >> 4) & 0x0f); + break; + case 0x08: + ret = ((mixer->regs[0x36] >> 4) & 0x0f); + break; + case 0x0e: + ret = 0x02; + break; + case 0x22: + ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); + break; + case 0x26: + ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); + break; + case 0x28: + ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); + break; + case 0x2e: + ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); + break; - case 0x80: - /*TODO: Unaffected by mixer reset or soft reboot. - * Enabling multiple bits enables multiple IRQs. - */ - - switch (sb->dsp.sb_irqnum) { - case 2: ret = 1; break; - case 5: ret = 2; break; - case 7: ret = 4; break; - case 10: ret = 8; break; - } - break; - - case 0x81: - /* TODO: Unaffected by mixer reset or soft reboot. - * Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. - * Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, - including translated 16-bit DMA requests. - * Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA - requests to 8-bit ones, using the selected 8-bit DMA channel.*/ - - ret = 0; - switch (sb->dsp.sb_8_dmanum) { - case 0: ret |= 1; break; - case 1: ret |= 2; break; - case 3: ret |= 8; break; - } - switch (sb->dsp.sb_16_dmanum) { - case 5: ret |= 0x20; break; - case 6: ret |= 0x40; break; - case 7: ret |= 0x80; break; - } - break; + case 0x48: + /* Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector), + even when writing. + Also, the version I have (5.17), does not use the MIDI.L/R input selectors, it uses + the volume to mute (Affecting the output, obviously). */ + ret = mixer->regs[mixer->index]; + break; - /* The Interrupt status register, addressed as register 82h on the Mixer register map, - is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, - in which case it should chain to the previous routine. - */ - case 0x82: - /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ - /* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */ - temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | - ((sb->dsp.sb_irq401) ? 4 : 0) | 0x4000; - ret = temp; - break; + case 0x80: + /* TODO: Unaffected by mixer reset or soft reboot. + Enabling multiple bits enables multiple IRQs. */ - case 0x83: - /* Interrupt mask. */ - ret = mixer->regs[mixer->index]; - break; - - case 0x84: - /* MPU Control. */ - if (sb->mpu == NULL) - ret = 0x02; - else { - if (sb->mpu->addr == 0x330) - ret = 0x00; - else if (sb->mpu->addr == 0x300) - ret = 0x04; - else if (sb->mpu->addr == 0) - ret = 0x02; - else - ret = 0x06; /* Should never happen. */ - } - break; - - case 0x90: - /* 3D Enhancement switch. */ - ret = mixer->regs[mixer->index]; - break; - - /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ - case 0xfd: - ret = 16; - break; - - case 0xfe: - ret = 6; - break; - - default: - sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); - break; - } - - sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret); - return ret; -} - -void sb_ct1745_mixer_reset(sb_t* sb) -{ - sb_ct1745_mixer_write(4,0,sb); - sb_ct1745_mixer_write(5,0,sb); - - sb->mixer_sb16.regs[0xfd] = 16; - sb->mixer_sb16.regs[0xfe] = 6; -} - - -static uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270}; - -uint8_t sb_mcv_read(int port, void *p) -{ - sb_t *sb = (sb_t *)p; - - sb_log("sb_mcv_read: port=%04x\n", port); - - return sb->pos_regs[port & 7]; -} - -void sb_mcv_write(int port, uint8_t val, void *p) -{ - uint16_t addr; - sb_t *sb = (sb_t *)p; - - if (port < 0x102) - return; - - sb_log("sb_mcv_write: port=%04x val=%02x\n", port, val); - - addr = sb_mcv_addr[sb->pos_regs[4] & 7]; - if (sb->opl_enabled) { - io_removehandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - } - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, 0); - - sb->pos_regs[port & 7] = val; - - if (sb->pos_regs[2] & 1) - { - addr = sb_mcv_addr[sb->pos_regs[4] & 7]; - - if (sb->opl_enabled) { - io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + switch (sb->dsp.sb_irqnum) { + case 2: ret = 1; break; + case 5: ret = 2; break; + case 7: ret = 4; break; + case 10: ret = 8; break; } - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, addr); - } -} + break; -uint8_t sb_mcv_feedb(void *p) -{ - sb_t *sb = (sb_t *)p; + case 0x81: + /* TODO: Unaffected by mixer reset or soft reboot. + Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. + Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, + including translated 16-bit DMA requests. + Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA + requests to 8-bit ones, using the selected 8-bit DMA channel. */ - return (sb->pos_regs[2] & 1); + ret = 0; + switch (sb->dsp.sb_8_dmanum) { + case 0: ret |= 1; break; + case 1: ret |= 2; break; + case 3: ret |= 8; break; + } + switch (sb->dsp.sb_16_dmanum) { + case 5: ret |= 0x20; break; + case 6: ret |= 0x40; break; + case 7: ret |= 0x80; break; + } + break; + + case 0x82: + /* The Interrupt status register, addressed as register 82h on the Mixer register map, + is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, + in which case it should chain to the previous routine. */ + /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ + /* 0x02000 DSP v4.04, 0x4000 DSP v4.05, 0x8000 DSP v4.12. + I haven't seen this making any difference, but I'm keeping it for now. */ + temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | + ((sb->dsp.sb_irq401) ? 4 : 0) | 0x4000; + ret = temp; + break; + + case 0x83: + /* Interrupt mask. */ + ret = mixer->regs[mixer->index]; + break; + + case 0x84: + /* MPU Control. */ + if (sb->mpu == NULL) + ret = 0x02; + else { + if (sb->mpu->addr == 0x330) + ret = 0x00; + else if (sb->mpu->addr == 0x300) + ret = 0x04; + else if (sb->mpu->addr == 0) + ret = 0x02; + else + ret = 0x06; /* Should never happen. */ + } + break; + + case 0x90: + /* 3D Enhancement switch. */ + ret = mixer->regs[mixer->index]; + break; + + /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ + case 0xfd: + ret = 16; + break; + + case 0xfe: + ret = 6; + break; + + default: + sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + break; + } + + sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret); + + return ret; } -static int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; - -uint8_t sb_pro_mcv_read(int port, void *p) +static void +sb_ct1745_mixer_reset(sb_t* sb) { - sb_t *sb = (sb_t *)p; + sb_ct1745_mixer_write(4, 0, sb); + sb_ct1745_mixer_write(5, 0, sb); - sb_log("sb_pro_mcv_read: port=%04x\n", port); - - return sb->pos_regs[port & 7]; + sb->mixer_sb16.regs[0xfd] = 16; + sb->mixer_sb16.regs[0xfe] = 6; } -void sb_pro_mcv_write(int port, uint8_t val, void *p) + +uint8_t +sb_mcv_read(int port, void *p) { - uint16_t addr; - sb_t *sb = (sb_t *)p; + sb_t *sb = (sb_t *)p; - if (port < 0x102) - return; + sb_log("sb_mcv_read: port=%04x\n", port); - sb_log("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); - - addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; - io_removehandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_removehandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, 0); - - sb->pos_regs[port & 7] = val; - - if (sb->pos_regs[2] & 1) - { - addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; - - io_sethandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - sb_dsp_setaddr(&sb->dsp, addr); - } - sb_dsp_setirq(&sb->dsp, sb_pro_mcv_irqs[(sb->pos_regs[5] >> 4) & 3]); - sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); + return sb->pos_regs[port & 7]; } -void *sb_1_init(const device_t *info) + +void +sb_mcv_write(int port, uint8_t val, void *p) { - /*sb1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl2_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); - 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 */ + uint16_t addr; + sb_t *sb = (sb_t *)p; + + if (port < 0x102) + return; + + sb_log("sb_mcv_write: port=%04x val=%02x\n", port, val); + + addr = sb_mcv_addr[sb->pos_regs[4] & 7]; + if (sb->opl_enabled) { + io_removehandler(addr + 8, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + } + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) { + addr = sb_mcv_addr[sb->pos_regs[4] & 7]; + if (sb->opl_enabled) { - io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); } - sound_add_handler(sb_get_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; -} -void *sb_15_init(const device_t *info) -{ - /*sb1/2 port mappings, 210h to 260h in 10h steps - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); - - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl2_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); - 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 */ - if (sb->opl_enabled) { - io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - } - sound_add_handler(sb_get_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); + } } -void *sb_mcv_init(const device_t *info) + +uint8_t +sb_mcv_feedb(void *p) { - /*sb1/2 port mappings, 210h to 260h in 10h steps - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = (sb_t *)p; - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl2_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); - sb_dsp_setaddr(&sb->dsp, 0);//addr); - sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); - sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sound_add_handler(sb_get_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - /* I/O handlers activated in sb_mcv_write */ - mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, NULL, sb); - sb->pos_regs[0] = 0x84; - sb->pos_regs[1] = 0x50; - - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); - - return sb; + return (sb->pos_regs[2] & 1); } -void *sb_2_init(const device_t *info) + + +static uint8_t +sb_pro_mcv_read(int port, void *p) { - /*sb2 port mappings. 220h or 240h. - 2x0 to 2x3 -> CMS chip - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip - "CD version" also uses 250h or 260h for - 2x0 to 2x3 -> CDROM interface - 2x4 to 2x5 -> Mixer interface*/ - /*My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is - disabled when the CMS chips are present. - This mirror may also exist on SB 1.5 & MCV, however I am unable to - test this. It shouldn't exist on SB 1.0 as the CMS chips are always - present there. - Syndicate requires this mirror for music to play.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = (sb_t *)p; + uint8_t ret = sb->pos_regs[port & 7]; - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl2_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb); - 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")); - 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 */ - if (sb->opl_enabled) { - if (!GAMEBLASTER) - io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); - } - - int mixer_addr = device_get_config_int("mixaddr"); - if (mixer_addr > 0) - { - io_sethandler(mixer_addr+4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, sb_ct1335_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_sb2_mixer, sb); - sound_set_cd_audio_filter(sb2_mixer_filter_cd_audio, sb); - } else { - sound_add_handler(sb_get_buffer_sb2, sb); - sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + sb_log("sb_pro_mcv_read: port=%04x ret=%02x\n", port, ret); + + return ret; +} + + +static void +sb_pro_mcv_write(int port, uint8_t val, void *p) +{ + uint16_t addr; + sb_t *sb = (sb_t *)p; + + if (port < 0x102) + return; + + sb_log("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); + + addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; + + io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_removehandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, 0); + + sb->pos_regs[port & 7] = val; + + if (sb->pos_regs[2] & 1) { + addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; + + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + sb_dsp_setaddr(&sb->dsp, addr); + } + + sb_dsp_setirq(&sb->dsp, sb_pro_mcv_irqs[(sb->pos_regs[5] >> 4) & 3]); + sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); +} + + +void * +sb_1_init(const device_t *info) +{ + /* SB1/2 port mappings, 210h to 260h in 10h steps + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip*/ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + memset(sb, 0, sizeof(sb_t)); + + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl2_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb); + 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 */ + if (sb->opl_enabled) { + io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + } + + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); + sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; +} + + +void * +sb_15_init(const device_t *info) +{ + /* SB1/2 port mappings, 210h to 260h in 10h steps + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip */ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + memset(sb, 0, sizeof(sb_t)); + + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl2_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); + 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 */ + if (sb->opl_enabled) { + io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + } + + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); + sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; +} + + +void * +sb_mcv_init(const device_t *info) +{ + /*SB1/2 port mappings, 210h to 260h in 10h steps + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip */ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0, sizeof(sb_t)); + + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl2_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb); + sb_dsp_setaddr(&sb->dsp, 0); + sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); + sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); + + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); + sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); + + /* I/O handlers activated in sb_mcv_write */ + mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, NULL, sb); + sb->pos_regs[0] = 0x84; + sb->pos_regs[1] = 0x50; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; +} + + +void * +sb_2_init(const device_t *info) +{ + /* SB2 port mappings. 220h or 240h. + 2x0 to 2x3 -> CMS chip + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip + "CD version" also uses 250h or 260h for + 2x0 to 2x3 -> CDROM interface + 2x4 to 2x5 -> Mixer interface */ + /* My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is disabled when the + CMS chips are present. + This mirror may also exist on SB 1.5 & MCV, however I am unable to test this. It shouldn't + exist on SB 1.0 as the CMS chips are always present there. Syndicate requires this mirror + for music to play.*/ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + uint16_t mixer_addr = device_get_config_int("mixaddr"); + + memset(sb, 0, sizeof(sb_t)); + + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl2_init(&sb->opl); + + sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb); + 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")); + 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 */ + if (sb->opl_enabled) { + if (!GAMEBLASTER) { + io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); } + io_sethandler(addr + 8, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + } - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (mixer_addr > 0x0000) { + sb->mixer_enabled = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1335_mixer_read, NULL, NULL, + sb_ct1335_mixer_write, NULL, NULL, sb); + } else + sb->mixer_enabled = 0; + sound_add_handler(sb_get_buffer_sb2, sb); + sound_set_cd_audio_filter(sb2_filter_cd_audio, sb); - return sb; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } @@ -1266,246 +1224,276 @@ sb_pro_v1_opl_write(uint16_t port, uint8_t val, void *priv) } -/*sbpro port mappings. 220h or 240h. - 2x0 to 2x1 -> FM chip, Left (9*2 voices) - 2x1 to 2x3 -> FM chip, Right (9*2 voices) - 2x4 to 2x5 -> Mixer interface - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip (9 voices) - 2x0+10 to 2x0+13 CDROM interface. -*/ -void *sb_pro_v1_init(const device_t *info) +static void * +sb_pro_v1_init(const device_t *info) { - /*sbpro port mappings. 220h or 240h. - 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) - 2x4 to 2x5 -> Mixer interface - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip (9 voices) - 2x0+10 to 2x0+13 CDROM interface.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); + /* SB Pro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices) + 2x0+10 to 2x0+13 CDROM interface. */ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + memset(sb, 0, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) { - opl2_init(&sb->opl); - opl_set_do_cycles(&sb->opl, 0); - opl2_init(&sb->opl2); - opl_set_do_cycles(&sb->opl2, 0); - } - sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); - 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")); - sb_ct1345_mixer_reset(sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - io_sethandler(addr + 0, 2, - opl2_read,NULL,NULL, opl2_write,NULL,NULL, &sb->opl); - io_sethandler(addr + 2, 2, - opl2_read,NULL,NULL, opl2_write,NULL,NULL, &sb->opl2); - io_sethandler(addr + 8, 2, - sb_pro_v1_opl_read,NULL,NULL, sb_pro_v1_opl_write,NULL,NULL, sb); - io_sethandler(0x0388, 2, - sb_pro_v1_opl_read,NULL,NULL, sb_pro_v1_opl_write,NULL,NULL, sb); - } - io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_sbpro, sb); - sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) { + opl2_init(&sb->opl); + opl_set_do_cycles(&sb->opl, 0); + opl2_init(&sb->opl2); + opl_set_do_cycles(&sb->opl2, 0); + } - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb); + 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")); + sb_ct1345_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + if (sb->opl_enabled) { + io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 2, 0x0002, opl2_read, NULL, NULL, + opl2_write, NULL, NULL, &sb->opl2); + io_sethandler(addr + 8, 0x0002, sb_pro_v1_opl_read, NULL, NULL, + sb_pro_v1_opl_write, NULL, NULL, sb); + io_sethandler(0x0388, 0x0002, sb_pro_v1_opl_read, NULL, NULL, + sb_pro_v1_opl_write, NULL, NULL, sb); + } - return sb; + sb->mixer_enabled = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sbpro, sb); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } -void *sb_pro_v2_init(const device_t *info) + +static void * +sb_pro_v2_init(const device_t *info) { - /*sbpro port mappings. 220h or 240h. - 2x0 to 2x3 -> FM chip (18 voices) - 2x4 to 2x5 -> Mixer interface - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip (9 voices) - 2x0+10 to 2x0+13 CDROM interface.*/ - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - memset(sb, 0, sizeof(sb_t)); + /* SB Pro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip (18 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices) + 2x0+10 to 2x0+13 CDROM interface. */ + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + memset(sb, 0, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); - 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")); - sb_ct1345_mixer_reset(sb); - /* DSP I/O handler is activated in sb_dsp_setaddr */ - if (sb->opl_enabled) { - io_sethandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - } - io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_sbpro, sb); - sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl3_init(&sb->opl); - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + 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")); + sb_ct1345_mixer_reset(sb); + /* DSP I/O handler is activated in sb_dsp_setaddr */ + if (sb->opl_enabled) { + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + } - return sb; + sb->mixer_enabled = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, + sb_ct1345_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sbpro, sb); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } -void *sb_pro_mcv_init(const device_t *info) + +static void * +sb_pro_mcv_init(const device_t *info) { - /*sbpro port mappings. 220h or 240h. - 2x0 to 2x3 -> FM chip, Left and Right (18 voices) - 2x4 to 2x5 -> Mixer interface - 2x6, 2xA, 2xC, 2xE -> DSP chip - 2x8, 2x9, 388 and 389 FM chip (9 voices)*/ - sb_t *sb = malloc(sizeof(sb_t)); - memset(sb, 0, sizeof(sb_t)); + /*SB Pro port mappings. 220h or 240h. + 2x0 to 2x3 -> FM chip, Left and Right (18 voices) + 2x4 to 2x5 -> Mixer interface + 2x6, 2xA, 2xC, 2xE -> DSP chip + 2x8, 2x9, 388 and 389 FM chip (9 voices) */ + sb_t *sb = malloc(sizeof(sb_t)); + memset(sb, 0, sizeof(sb_t)); - sb->opl_enabled = 1; - opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); - sb_ct1345_mixer_reset(sb); - /* I/O handlers activated in sb_mcv_write */ - sound_add_handler(sb_get_buffer_sbpro, sb); - sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); + sb->opl_enabled = 1; + opl3_init(&sb->opl); - /* I/O handlers activated in sb_pro_mcv_write */ - mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb_mcv_feedb, NULL, sb); - sb->pos_regs[0] = 0x03; - sb->pos_regs[1] = 0x51; + sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb); + sb_ct1345_mixer_reset(sb); - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + sb->mixer_enabled = 1; + sound_add_handler(sb_get_buffer_sbpro, sb); + sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb); - return sb; + /* I/O handlers activated in sb_pro_mcv_write */ + mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb_mcv_feedb, NULL, sb); + sb->pos_regs[0] = 0x03; + sb->pos_regs[1] = 0x51; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } -void *sb_16_init(const device_t *info) + +static void * +sb_16_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - uint16_t mpu_addr = device_get_config_hex16("base401"); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + uint16_t mpu_addr = device_get_config_hex16("base401"); - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); - 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")); - sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); - sb_ct1745_mixer_reset(sb); - if (sb->opl_enabled) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - } - io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_sb16, sb); - sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); - if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); - } else - sb->mpu = NULL; - sb_dsp_set_mpu(&sb->dsp, sb->mpu); + memset(sb, 0x00, sizeof(sb_t)); - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl3_init(&sb->opl); - return sb; + sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb); + 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")); + sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); + sb_ct1745_mixer_reset(sb); + + if (sb->opl_enabled) { + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + } + + sb->mixer_enabled = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + + if (mpu_addr) { + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + } else + sb->mpu = NULL; + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } -int sb_awe32_available() + +static int +sb_awe32_available() { - return rom_present(L"roms/sound/awe32.raw"); + return rom_present(L"roms/sound/awe32.raw"); } -void *sb_awe32_init(const device_t *info) + +static void * +sb_awe32_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); - uint16_t addr = device_get_config_hex16("base"); - uint16_t mpu_addr = device_get_config_hex16("base401"); - uint16_t emu_addr = device_get_config_hex16("emu_base"); - int onboard_ram = device_get_config_int("onboard_ram"); - memset(sb, 0, sizeof(sb_t)); + sb_t *sb = malloc(sizeof(sb_t)); + uint16_t addr = device_get_config_hex16("base"); + uint16_t mpu_addr = device_get_config_hex16("base401"); + uint16_t emu_addr = device_get_config_hex16("emu_base"); + int onboard_ram = device_get_config_int("onboard_ram"); + memset(sb, 0x00, sizeof(sb_t)); - sb->opl_enabled = device_get_config_int("opl"); - if (sb->opl_enabled) - opl3_init(&sb->opl); + sb->opl_enabled = device_get_config_int("opl"); + if (sb->opl_enabled) + opl3_init(&sb->opl); - sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); - 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")); - sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); - sb_ct1745_mixer_reset(sb); - if (sb->opl_enabled) { - io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - } - io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); - sound_add_handler(sb_get_buffer_emu8k, sb); - sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); - if (mpu_addr) { - sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); - memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); - sb_dsp_set_mpu(&sb->dsp, sb->mpu); - } else - sb->mpu = NULL; - emu8k_init(&sb->emu8k, emu_addr, onboard_ram); + sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb); + 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")); + sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); + sb_ct1745_mixer_reset(sb); - if (device_get_config_int("receive_input")) - midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + if (sb->opl_enabled) { + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + } - return sb; + sb->mixer_enabled = 1; + io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, + sb_ct1745_mixer_write, NULL, NULL, sb); + sound_add_handler(sb_get_buffer_sb16_awe32, sb); + sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb); + + if (mpu_addr) { + sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + } else + sb->mpu = NULL; + sb_dsp_set_mpu(&sb->dsp, sb->mpu); + + emu8k_init(&sb->emu8k, emu_addr, onboard_ram); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + + return sb; } -void sb_close(void *p) + +void +sb_close(void *p) { - sb_t *sb = (sb_t *)p; - sb_dsp_close(&sb->dsp); - #ifdef SB_DSP_RECORD_DEBUG - if (soundfsb != 0) - { - fclose(soundfsb); - soundfsb=0; - } - if (soundfsbin!= 0) - { - fclose(soundfsbin); - soundfsbin=0; - } - #endif - - free(sb); + sb_t *sb = (sb_t *)p; + sb_dsp_close(&sb->dsp); + + free(sb); } -void sb_awe32_close(void *p) -{ - sb_t *sb = (sb_t *)p; - - emu8k_close(&sb->emu8k); - sb_close(sb); +static void +sb_awe32_close(void *p) +{ + sb_t *sb = (sb_t *)p; + + emu8k_close(&sb->emu8k); + + sb_close(sb); } -void sb_speed_changed(void *p) + +void +sb_speed_changed(void *p) { - sb_t *sb = (sb_t *)p; - - sb_dsp_speed_changed(&sb->dsp); + sb_t *sb = (sb_t *)p; + + sb_dsp_speed_changed(&sb->dsp); } + static const device_config_t sb_config[] = { { @@ -2014,7 +2002,7 @@ const device_t sb_awe32_device = "Sound Blaster AWE32", DEVICE_ISA, 0, - sb_awe32_init, sb_close, NULL, + sb_awe32_init, sb_awe32_close, NULL, sb_awe32_available, sb_speed_changed, NULL, diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 30b5ae23a..4c0bcf6ab 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -117,7 +117,7 @@ uint8_t adjustMap2[24] = { 252, 0, 252, 0 }; -float low_fir_sb16_coef[SB16_NCoef]; +double low_fir_sb16_coef[2][SB16_NCoef]; #ifdef ENABLE_SB_DSP_LOG @@ -147,13 +147,13 @@ sinc(double x) } static void -recalc_sb16_filter(int playback_freq) +recalc_sb16_filter(int c, int playback_freq) { /* Cutoff frequency = playback / 2 */ - float fC = ((float)playback_freq / 2.0) / 48000.0; - float gain; int n; double w, h; + double fC = ((double) playback_freq) / 96000.0; + double gain; for (n = 0; n < SB16_NCoef; n++) { /* Blackman window */ @@ -162,18 +162,18 @@ recalc_sb16_filter(int playback_freq) h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0))); /* Create windowed-sinc filter */ - low_fir_sb16_coef[n] = w * h; + low_fir_sb16_coef[c][n] = w * h; } - low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0; + low_fir_sb16_coef[c][(SB16_NCoef - 1) / 2] = 1.0; gain = 0.0; for (n = 0; n < SB16_NCoef; n++) - gain += low_fir_sb16_coef[n]; + gain += low_fir_sb16_coef[c][n]; /* Normalise filter, to produce unity gain */ for (n = 0; n < SB16_NCoef; n++) - low_fir_sb16_coef[n] /= gain; + low_fir_sb16_coef[c][n] /= gain; } @@ -555,7 +555,7 @@ sb_exec_command(sb_dsp_t *dsp) temp = 1000000 / temp; sb_dsp_log("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); if ((dsp->sb_freq != temp) && (dsp->sb_type >= SB16)) - recalc_sb16_filter(temp); + recalc_sb16_filter(0, temp); dsp->sb_freq = temp; break; case 0x41: /* Set output sampling rate */ @@ -569,7 +569,7 @@ sb_exec_command(sb_dsp_t *dsp) dsp->sblatchi = dsp->sblatcho; dsp->sb_timei = dsp->sb_timeo; if (dsp->sb_freq != temp && dsp->sb_type >= SB16) - recalc_sb16_filter(dsp->sb_freq); + recalc_sb16_filter(0, dsp->sb_freq); } break; case 0x48: /* Set DSP block transfer size */ @@ -1046,7 +1046,8 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) /* Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when a set frequency command is sent. */ - recalc_sb16_filter(3200*2); + recalc_sb16_filter(0, 3200*2); + recalc_sb16_filter(1, 44100); } diff --git a/src/sound/sound.c b/src/sound/sound.c index c50d002c6..310a38ca2 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -77,7 +77,7 @@ static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN; static volatile int cdaudioon = 0; static int cd_thread_enable = 0; -static void (*filter_cd_audio)(int channel, float *buffer, void *p) = NULL; +static void (*filter_cd_audio)(int channel, double *buffer, void *p) = NULL; static void *filter_cd_audio_p = NULL; @@ -215,8 +215,8 @@ static void sound_cd_thread(void *param) { int c, r, i, channel_select[2]; - float audio_vol_l, audio_vol_r; - float cd_buffer_temp[2] = {0.0, 0.0}; + double audio_vol_l, audio_vol_r; + double cd_buffer_temp[2] = {0.0, 0.0}; thread_set_event(sound_cd_start_event); @@ -274,18 +274,18 @@ sound_cd_thread(void *param) if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) { if (channel_select[0] & 1) - cd_buffer_temp[0] += ((float) cd_buffer[i][c]); /* Channel 0 => Port 0 */ + cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */ if (channel_select[0] & 2) - cd_buffer_temp[0] += ((float) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ + cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ } if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { if (channel_select[1] & 1) - cd_buffer_temp[1] += ((float) cd_buffer[i][c]); /* Channel 0 => Port 1 */ + cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */ if (channel_select[1] & 2) - cd_buffer_temp[1] += ((float) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ + cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ } @@ -297,8 +297,8 @@ sound_cd_thread(void *param) } if (sound_is_float) { - cd_out_buffer[c] += (cd_buffer_temp[0] / 32768.0); - cd_out_buffer[c+1] += (cd_buffer_temp[1] / 32768.0); + cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0); + cd_out_buffer[c+1] += (float) (cd_buffer_temp[1] / 32768.0); } else { if (cd_buffer_temp[0] > 32767) cd_buffer_temp[0] = 32767; @@ -309,8 +309,8 @@ sound_cd_thread(void *param) if (cd_buffer_temp[1] < -32768) cd_buffer_temp[1] = -32768; - cd_out_buffer_int16[c] += cd_buffer_temp[0]; - cd_out_buffer_int16[c+1] += cd_buffer_temp[1]; + cd_out_buffer_int16[c] += (int16_t) cd_buffer_temp[0]; + cd_out_buffer_int16[c+1] += (int16_t) cd_buffer_temp[1]; } } } @@ -384,7 +384,7 @@ sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p void -sound_set_cd_audio_filter(void (*filter)(int channel, float *buffer, void *p), void *p) +sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *p), void *p) { if ((filter_cd_audio == NULL) || (filter == NULL)) { filter_cd_audio = filter; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index f92021165..0f6c37dbb 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -912,10 +912,8 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->overlay_draw = overlay_draw; svga->hwcursor.xsize = svga->hwcursor.ysize = 32; - svga->hwcursor.yoff = 32; svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = 32; - svga->dac_hwcursor.yoff = 32; svga->translate_address = NULL; svga->ksc5601_english_font_type = 0; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 74b8c42ad..c45de5a5f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -117,6 +117,9 @@ ifeq ($(DEV_BUILD), y) ifndef USE_VECT486VL USE_VECT486VL := y endif + ifndef USE_DELLS4 + USE_DELLS4 := y + endif else ifndef DEBUG DEBUG := n @@ -208,6 +211,9 @@ else ifndef USE_VECT486VL USE_VECT486VL := n endif + ifndef USE_DELLS4 + USE_DELLS4 := n + endif endif # Defaults for several build options (possibly defined in a chained file.) @@ -630,6 +636,10 @@ ifeq ($(USE_VECT486VL), y) OPTS += -DUSE_VECT486VL endif +ifeq ($(USE_DELLS4), y) +OPTS += -DUSE_DELLS4 +endif + endif