PCem
changeset 33:83416bce6aae
Split off AD1848 CODEC from main Windows Sound System emulation.
| author | TomW |
|---|---|
| date | Tue Nov 05 19:59:35 2013 +0000 |
| parents | f50409fd5bac |
| children | 35e71a08b4ed |
| files | src/sound_ad1848.c src/sound_ad1848.h src/sound_wss.c |
| diffstat | 3 files changed, 249 insertions(+), 196 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/sound_ad1848.c Tue Nov 05 19:59:35 2013 +0000 1.3 @@ -0,0 +1,204 @@ 1.4 +/*PCem v0.8 by Tom Walker 1.5 + 1.6 + AD1848 CODEC emulation (Windows Sound System compatible)*/ 1.7 + 1.8 +#include "ibm.h" 1.9 +#include "sound_ad1848.h" 1.10 + 1.11 +static int ad1848_vols[64]; 1.12 + 1.13 +void ad1848_setirq(ad1848_t *ad1848, int irq) 1.14 +{ 1.15 + ad1848->irq = irq; 1.16 +} 1.17 + 1.18 +void ad1848_setdma(ad1848_t *ad1848, int dma) 1.19 +{ 1.20 + ad1848->dma = dma; 1.21 +} 1.22 + 1.23 +uint8_t ad1848_read(uint16_t addr, void *p) 1.24 +{ 1.25 + ad1848_t *ad1848 = (ad1848_t *)p; 1.26 + uint8_t temp = 0xff; 1.27 +// pclog("ad1848_read - addr %04X %04X(%08X):%08X ", addr, CS, cs, pc); 1.28 + switch (addr & 3) 1.29 + { 1.30 + case 0: /*Index*/ 1.31 + temp = ad1848->index | ad1848->trd | ad1848->mce; 1.32 + break; 1.33 + case 1: 1.34 + temp = ad1848->regs[ad1848->index]; 1.35 + break; 1.36 + case 2: 1.37 + temp = ad1848->status; 1.38 + break; 1.39 + } 1.40 +// pclog("return %02X\n", temp); 1.41 + return temp; 1.42 +} 1.43 + 1.44 +void ad1848_write(uint16_t addr, uint8_t val, void *p) 1.45 +{ 1.46 + ad1848_t *ad1848 = (ad1848_t *)p; 1.47 + double freq; 1.48 +// pclog("ad1848_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, pc); 1.49 + switch (addr & 3) 1.50 + { 1.51 + case 0: /*Index*/ 1.52 + ad1848->index = val & 0xf; 1.53 + ad1848->trd = val & 0x20; 1.54 + ad1848->mce = val & 0x40; 1.55 + break; 1.56 + case 1: 1.57 + switch (ad1848->index) 1.58 + { 1.59 + case 8: 1.60 + freq = (val & 1) ? 16934400 : 24576000; 1.61 + switch ((val >> 1) & 7) 1.62 + { 1.63 + case 0: freq /= 3072; break; 1.64 + case 1: freq /= 1536; break; 1.65 + case 2: freq /= 896; break; 1.66 + case 3: freq /= 768; break; 1.67 + case 4: freq /= 448; break; 1.68 + case 5: freq /= 384; break; 1.69 + case 6: freq /= 512; break; 1.70 + case 7: freq /= 2560; break; 1.71 + } 1.72 + ad1848->inc = (int)((freq * 65536) / 48000); 1.73 + break; 1.74 + 1.75 + case 9: 1.76 + if (!ad1848->enable) 1.77 + ad1848->interp_count = 0; 1.78 + 1.79 + ad1848->enable = ((val & 0x41) == 0x01); 1.80 + break; 1.81 + 1.82 + case 12: 1.83 + return; 1.84 + 1.85 + case 14: 1.86 + ad1848->count = ad1848->regs[15] | (val << 8); 1.87 + break; 1.88 + } 1.89 + ad1848->regs[ad1848->index] = val; 1.90 + break; 1.91 + case 2: 1.92 + ad1848->status &= 0xfe; 1.93 + break; 1.94 + } 1.95 +} 1.96 + 1.97 +void ad1848_poll(void *p, int16_t *l, int16_t *r) 1.98 +{ 1.99 + ad1848_t *ad1848 = (ad1848_t *)p; 1.100 + 1.101 +// opl3_poll(&ad1848->opl, &ad1848->opl_buffer[ad1848->pos * 2], &ad1848->opl_buffer[(ad1848->pos * 2) + 1]); 1.102 + 1.103 + if (ad1848->enable) 1.104 + { 1.105 + int32_t temp; 1.106 + 1.107 + if (ad1848->regs[6] & 0x80) 1.108 + *l = 0; 1.109 + else 1.110 + *l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16; 1.111 + 1.112 + if (ad1848->regs[7] & 0x80) 1.113 + *r = 0; 1.114 + else 1.115 + *r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16; 1.116 + 1.117 + ad1848->interp_count += ad1848->inc; 1.118 + if (ad1848->interp_count >= 0x10000) 1.119 + { 1.120 + ad1848->interp_count -= 0x10000; 1.121 + 1.122 + if (ad1848->count < 0) 1.123 + { 1.124 + ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8); 1.125 + if (!(ad1848->status & 0x01)) 1.126 + { 1.127 + ad1848->status |= 0x01; 1.128 + if (ad1848->regs[0xa] & 2) 1.129 + picint(1 << ad1848->irq); 1.130 + } 1.131 + } 1.132 + 1.133 + switch (ad1848->regs[8] & 0x70) 1.134 + { 1.135 + case 0x00: /*Mono, 8-bit PCM*/ 1.136 + ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; 1.137 + break; 1.138 + case 0x10: /*Stereo, 8-bit PCM*/ 1.139 + ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; 1.140 + ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256; 1.141 + break; 1.142 + 1.143 + case 0x40: /*Mono, 16-bit PCM*/ 1.144 + temp = dma_channel_read(ad1848->dma); 1.145 + ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); 1.146 + break; 1.147 + case 0x50: /*Stereo, 16-bit PCM*/ 1.148 + temp = dma_channel_read(ad1848->dma); 1.149 + ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8); 1.150 + temp = dma_channel_read(ad1848->dma); 1.151 + ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8); 1.152 + break; 1.153 + } 1.154 + 1.155 + ad1848->count--; 1.156 + } 1.157 +// pclog("ad1848_poll : enable %X %X %X %X %X %X\n", ad1848->pcm_buffer[0][ad1848->pos], ad1848->pcm_buffer[1][ad1848->pos], ad1848->out_l[0], ad1848->out_r[0], ad1848->out_l[1], ad1848->out_r[1]); 1.158 + } 1.159 + else 1.160 + { 1.161 + *l = *r = 0; 1.162 +// pclog("ad1848_poll : not enable\n"); 1.163 + } 1.164 +} 1.165 + 1.166 +void ad1848_init(ad1848_t *ad1848) 1.167 +{ 1.168 + int c; 1.169 + double attenuation; 1.170 + 1.171 + ad1848->enable = 0; 1.172 + 1.173 + ad1848->status = 0xcc; 1.174 + ad1848->index = ad1848->trd = 0; 1.175 + ad1848->mce = 0x40; 1.176 + 1.177 + ad1848->regs[0] = ad1848->regs[1] = 0; 1.178 + ad1848->regs[2] = ad1848->regs[3] = 0x80; 1.179 + ad1848->regs[4] = ad1848->regs[5] = 0x80; 1.180 + ad1848->regs[6] = ad1848->regs[7] = 0x80; 1.181 + ad1848->regs[8] = 0; 1.182 + ad1848->regs[9] = 0x08; 1.183 + ad1848->regs[10] = ad1848->regs[11] = 0; 1.184 + ad1848->regs[12] = 0xa; 1.185 + ad1848->regs[13] = 0; 1.186 + ad1848->regs[14] = ad1848->regs[15] = 0; 1.187 + 1.188 + ad1848->out_l = 0; 1.189 + ad1848->out_r = 0; 1.190 + ad1848->interp_count = 0; 1.191 + 1.192 + for (c = 0; c < 64; c++) 1.193 + { 1.194 + attenuation = 0.0; 1.195 + if (c & 0x01) attenuation -= 1.5; 1.196 + if (c & 0x02) attenuation -= 3.0; 1.197 + if (c & 0x04) attenuation -= 6.0; 1.198 + if (c & 0x08) attenuation -= 12.0; 1.199 + if (c & 0x10) attenuation -= 24.0; 1.200 + if (c & 0x20) attenuation -= 48.0; 1.201 + 1.202 + attenuation = pow(10, attenuation / 10); 1.203 + 1.204 + ad1848_vols[c] = (int)(attenuation * 65536); 1.205 +// pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]); 1.206 + } 1.207 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/sound_ad1848.h Tue Nov 05 19:59:35 2013 +0000 2.3 @@ -0,0 +1,27 @@ 2.4 +typedef struct ad1848_t 2.5 +{ 2.6 + int index; 2.7 + uint8_t regs[16]; 2.8 + uint8_t status; 2.9 + 2.10 + int trd; 2.11 + int mce; 2.12 + 2.13 + int count; 2.14 + 2.15 + int16_t out_l, out_r; 2.16 + 2.17 + int interp_count, inc; 2.18 + 2.19 + int enable; 2.20 + 2.21 + int irq, dma; 2.22 +} ad1848_t; 2.23 + 2.24 +void ad1848_setirq(ad1848_t *ad1848, int irq); 2.25 +void ad1848_setdma(ad1848_t *ad1848, int dma); 2.26 + 2.27 +uint8_t ad1848_read(uint16_t addr, void *p); 2.28 +void ad1848_write(uint16_t addr, uint8_t val, void *p); 2.29 + 2.30 +void ad1848_poll(void *p, int16_t *l, int16_t *r);
3.1 --- a/src/sound_wss.c Tue Nov 05 11:02:25 2013 +0000 3.2 +++ b/src/sound_wss.c Tue Nov 05 19:59:35 2013 +0000 3.3 @@ -1,6 +1,6 @@ 3.4 /*PCem v0.8 by Tom Walker 3.5 3.6 - Windows Sound System compatible CODEC emulation (AD1848)*/ 3.7 + Windows Sound System emulation*/ 3.8 3.9 #include <math.h> 3.10 #include <stdlib.h> 3.11 @@ -10,6 +10,7 @@ 3.12 #include "dma.h" 3.13 #include "io.h" 3.14 #include "pic.h" 3.15 +#include "sound_ad1848.h" 3.16 #include "sound_opl.h" 3.17 #include "sound_wss.h" 3.18 3.19 @@ -31,24 +32,8 @@ 3.20 typedef struct wss_t 3.21 { 3.22 uint8_t config; 3.23 - 3.24 - int index; 3.25 - uint8_t regs[16]; 3.26 - uint8_t status; 3.27 - 3.28 - int trd; 3.29 - int mce; 3.30 - 3.31 - int count; 3.32 - 3.33 - int16_t out_l, out_r; 3.34 - 3.35 - int interp_count, inc; 3.36 3.37 - int enable; 3.38 - 3.39 - int irq, dma; 3.40 - 3.41 + ad1848_t ad1848; 3.42 opl_t opl; 3.43 3.44 int16_t opl_buffer[SOUNDBUFLEN * 2]; 3.45 @@ -57,29 +42,12 @@ 3.46 int pos; 3.47 } wss_t; 3.48 3.49 -static int wss_vols[64]; 3.50 - 3.51 uint8_t wss_read(uint16_t addr, void *p) 3.52 { 3.53 wss_t *wss = (wss_t *)p; 3.54 - uint8_t temp = 0xff; 3.55 + uint8_t temp; 3.56 // pclog("wss_read - addr %04X %04X(%08X):%08X ", addr, CS, cs, pc); 3.57 - switch (addr & 7) 3.58 - { 3.59 - case 0: case 1: case 2: case 3: /*Version*/ 3.60 - temp = 4 | (wss->config & 0x40); 3.61 - break; 3.62 - 3.63 - case 4: /*Index*/ 3.64 - temp = wss->index | wss->trd | wss->mce; 3.65 - break; 3.66 - case 5: 3.67 - temp = wss->regs[wss->index]; 3.68 - break; 3.69 - case 6: 3.70 - temp = wss->status; 3.71 - break; 3.72 - } 3.73 + temp = 4 | (wss->config & 0x40); 3.74 // pclog("return %02X\n", temp); 3.75 return temp; 3.76 } 3.77 @@ -87,60 +55,11 @@ 3.78 void wss_write(uint16_t addr, uint8_t val, void *p) 3.79 { 3.80 wss_t *wss = (wss_t *)p; 3.81 - double freq; 3.82 - pclog("wss_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, pc); 3.83 - switch (addr & 7) 3.84 - { 3.85 - case 0: case 1: case 2: case 3: /*Config*/ 3.86 - wss->config = val; 3.87 - wss->dma = wss_dma[val & 3]; 3.88 - wss->irq = wss_irq[(val >> 3) & 7]; 3.89 - break; 3.90 - 3.91 - case 4: /*Index*/ 3.92 - wss->index = val & 0xf; 3.93 - wss->trd = val & 0x20; 3.94 - wss->mce = val & 0x40; 3.95 - break; 3.96 - case 5: 3.97 - switch (wss->index) 3.98 - { 3.99 - case 8: 3.100 - freq = (val & 1) ? 16934400 : 24576000; 3.101 - switch ((val >> 1) & 7) 3.102 - { 3.103 - case 0: freq /= 3072; break; 3.104 - case 1: freq /= 1536; break; 3.105 - case 2: freq /= 896; break; 3.106 - case 3: freq /= 768; break; 3.107 - case 4: freq /= 448; break; 3.108 - case 5: freq /= 384; break; 3.109 - case 6: freq /= 512; break; 3.110 - case 7: freq /= 2560; break; 3.111 - } 3.112 - wss->inc = (int)((freq * 65536) / 48000); 3.113 - break; 3.114 - 3.115 - case 9: 3.116 - if (!wss->enable) 3.117 - wss->interp_count = 0; 3.118 - 3.119 - wss->enable = ((val & 0x41) == 0x01); 3.120 - break; 3.121 - 3.122 - case 12: 3.123 - return; 3.124 - 3.125 - case 14: 3.126 - wss->count = wss->regs[15] | (val << 8); 3.127 - break; 3.128 - } 3.129 - wss->regs[wss->index] = val; 3.130 - break; 3.131 - case 6: 3.132 - wss->status &= 0xfe; 3.133 - break; 3.134 - } 3.135 +// pclog("wss_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, pc); 3.136 + 3.137 + wss->config = val; 3.138 + ad1848_setdma(&wss->ad1848, wss_dma[val & 3]); 3.139 + ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]); 3.140 } 3.141 3.142 static void wss_poll(void *p) 3.143 @@ -151,68 +70,8 @@ 3.144 return; 3.145 3.146 opl3_poll(&wss->opl, &wss->opl_buffer[wss->pos * 2], &wss->opl_buffer[(wss->pos * 2) + 1]); 3.147 - 3.148 - if (wss->enable) 3.149 - { 3.150 - int32_t temp; 3.151 - 3.152 - if (wss->regs[6] & 0x80) 3.153 - wss->pcm_buffer[1][wss->pos] = 0; 3.154 - else 3.155 - wss->pcm_buffer[1][wss->pos] = (wss->out_l * wss_vols[wss->regs[6] & 0x3f]) >> 16; 3.156 + ad1848_poll(&wss->ad1848, &wss->pcm_buffer[0][wss->pos], &wss->pcm_buffer[1][wss->pos]); 3.157 3.158 - if (wss->regs[7] & 0x80) 3.159 - wss->pcm_buffer[0][wss->pos] = 0; 3.160 - else 3.161 - wss->pcm_buffer[0][wss->pos] = (wss->out_r * wss_vols[wss->regs[7] & 0x3f]) >> 16; 3.162 - 3.163 - wss->interp_count += wss->inc; 3.164 - if (wss->interp_count >= 0x10000) 3.165 - { 3.166 - wss->interp_count -= 0x10000; 3.167 - 3.168 - if (wss->count < 0) 3.169 - { 3.170 - wss->count = wss->regs[15] | (wss->regs[14] << 8); 3.171 - if (!(wss->status & 0x01)) 3.172 - { 3.173 - wss->status |= 0x01; 3.174 - if (wss->regs[0xa] & 2) 3.175 - picint(1 << wss->irq); 3.176 - } 3.177 - } 3.178 - 3.179 - switch (wss->regs[8] & 0x70) 3.180 - { 3.181 - case 0x00: /*Mono, 8-bit PCM*/ 3.182 - wss->out_l = wss->out_r = (dma_channel_read(wss->dma) ^ 0x80) * 256; 3.183 - break; 3.184 - case 0x10: /*Stereo, 8-bit PCM*/ 3.185 - wss->out_l = (dma_channel_read(wss->dma) ^ 0x80) * 256; 3.186 - wss->out_r = (dma_channel_read(wss->dma) ^ 0x80) * 256; 3.187 - break; 3.188 - 3.189 - case 0x40: /*Mono, 16-bit PCM*/ 3.190 - temp = dma_channel_read(wss->dma); 3.191 - wss->out_l = wss->out_r = dma_channel_read(wss->dma) | (temp << 8); 3.192 - break; 3.193 - case 0x50: /*Stereo, 16-bit PCM*/ 3.194 - temp = dma_channel_read(wss->dma); 3.195 - wss->out_l = dma_channel_read(wss->dma) | (temp << 8); 3.196 - temp = dma_channel_read(wss->dma); 3.197 - wss->out_r = dma_channel_read(wss->dma) | (temp << 8); 3.198 - break; 3.199 - } 3.200 - 3.201 - wss->count--; 3.202 - } 3.203 -// pclog("wss_poll : enable %X %X %X %X %X %X\n", wss->pcm_buffer[0][wss->pos], wss->pcm_buffer[1][wss->pos], wss->out_l[0], wss->out_r[0], wss->out_l[1], wss->out_r[1]); 3.204 - } 3.205 - else 3.206 - { 3.207 - wss->pcm_buffer[0][wss->pos] = wss->pcm_buffer[1][wss->pos] = 0; 3.208 -// pclog("wss_poll : not enable\n"); 3.209 - } 3.210 wss->pos++; 3.211 } 3.212 3.213 @@ -240,54 +99,17 @@ 3.214 memset(wss, 0, sizeof(wss_t)); 3.215 3.216 opl3_init(&wss->opl); 3.217 + ad1848_init(&wss->ad1848); 3.218 3.219 - pclog("wss_init - %i %i\n", sbtype, SND_WSS); 3.220 + ad1848_setirq(&wss->ad1848, 7); 3.221 + ad1848_setdma(&wss->ad1848, 3); 3.222 3.223 - wss->enable = 0; 3.224 - 3.225 - wss->status = 0xcc; 3.226 - wss->index = wss->trd = 0; 3.227 - wss->mce = 0x40; 3.228 - 3.229 - wss->regs[0] = wss->regs[1] = 0; 3.230 - wss->regs[2] = wss->regs[3] = 0x80; 3.231 - wss->regs[4] = wss->regs[5] = 0x80; 3.232 - wss->regs[6] = wss->regs[7] = 0x80; 3.233 - wss->regs[8] = 0; 3.234 - wss->regs[9] = 0x08; 3.235 - wss->regs[10] = wss->regs[11] = 0; 3.236 - wss->regs[12] = 0xa; 3.237 - wss->regs[13] = 0; 3.238 - wss->regs[14] = wss->regs[15] = 0; 3.239 - 3.240 - wss->out_l = 0; 3.241 - wss->out_r = 0; 3.242 - wss->interp_count = 0; 3.243 - 3.244 - wss->irq = 7; 3.245 - wss->dma = 3; 3.246 - 3.247 - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); 3.248 - io_sethandler(0x0530, 0x0008, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); 3.249 - 3.250 + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); 3.251 + io_sethandler(0x0530, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); 3.252 + io_sethandler(0x0534, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); 3.253 + 3.254 sound_add_handler(wss_poll, wss_get_buffer, wss); 3.255 3.256 - for (c = 0; c < 64; c++) 3.257 - { 3.258 - attenuation = 0.0; 3.259 - if (c & 0x01) attenuation -= 1.5; 3.260 - if (c & 0x02) attenuation -= 3.0; 3.261 - if (c & 0x04) attenuation -= 6.0; 3.262 - if (c & 0x08) attenuation -= 12.0; 3.263 - if (c & 0x10) attenuation -= 24.0; 3.264 - if (c & 0x20) attenuation -= 48.0; 3.265 - 3.266 - attenuation = pow(10, attenuation / 10); 3.267 - 3.268 - wss_vols[c] = (int)(attenuation * 65536); 3.269 - pclog("wss_vols %i = %f %i\n", c, attenuation, wss_vols[c]); 3.270 - } 3.271 - 3.272 return wss; 3.273 } 3.274
