From f545c7f1e6166ba06339218c149988eae218003c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 26 Jul 2020 01:13:03 +0200 Subject: [PATCH 1/3] OPL3 timers rewrite, DOOM OPL3 now actually appears to be in stereo. --- src/include/86box/snd_opl.h | 3 +- src/sound/snd_opl.c | 138 +++++++++++++++++++++--------------- src/sound/snd_opl_nuked.c | 2 +- src/sound/snd_sb.c | 26 ++++--- 4 files changed, 101 insertions(+), 68 deletions(-) diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index f01ea0214..38077e1d3 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -38,7 +38,8 @@ typedef struct { uint8_t status; uint8_t status_mask; uint8_t timer_ctrl; - uint16_t timer[2]; + uint16_t timer_count[2], + timer_cur_count[2]; pc_timer_t timers[2]; diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 07a7370fe..7fbfd3fc6 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -51,35 +51,66 @@ enum { }; -static void -status_update(opl_t *dev) -{ - if (dev->status & (STATUS_TIMER_1 | STATUS_TIMER_2) & dev->status_mask) - dev->status |= STATUS_TIMER_ALL; - else - dev->status &= ~STATUS_TIMER_ALL; -} +#ifdef ENABLE_OPL_LOG +int opl_do_log = ENABLE_OPL_LOG; static void -timer_set(opl_t *dev, int timer, uint64_t period) +opl_log(const char *fmt, ...) { - timer_on_auto(&dev->timers[timer], ((double) period) * 20.0); + va_list ap; + + if (opl_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } +#else +#define opl_log(fmt, ...) +#endif static void timer_over(opl_t *dev, int tmr) { - if (tmr) { + opl_log("Count wrapped around to zero, reloading timer %i...\n", tmr); + + if (tmr == 1) { dev->status |= STATUS_TIMER_2; - timer_set(dev, 1, dev->timer[1] * 16); + dev->timer_cur_count[1] = dev->timer_count[1]; } else { dev->status |= STATUS_TIMER_1; - timer_set(dev, 0, dev->timer[0] * 4); + dev->timer_cur_count[0] = dev->timer_count[0]; } +} - status_update(dev); + +static void +timer_tick(opl_t *dev, int tmr) +{ + dev->timer_cur_count[tmr] = (dev->timer_cur_count[tmr] + 1) & 0xff; + + opl_log("Ticking timer %i, count now %02X...\n", tmr, dev->timer_cur_count[tmr]); + + if (dev->timer_cur_count[tmr] == 0x00) + timer_over(dev, tmr); + + timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); +} + + +static void +timer_control(opl_t *dev, int tmr, int start) +{ + timer_on_auto(&dev->timers[tmr], 0.0); + + if (start) { + opl_log("Loading timer %i count: %02X = %02X\n", tmr, dev->timer_cur_count[tmr], dev->timer_count[tmr]); + dev->timer_cur_count[tmr] = dev->timer_count[tmr]; + timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); + } else + opl_log("Timer %i stopped\n", tmr); } @@ -88,7 +119,7 @@ timer_1(void *priv) { opl_t *dev = (opl_t *)priv; - timer_over(dev, 0); + timer_tick(dev, 0); } @@ -97,27 +128,56 @@ timer_2(void *priv) { opl_t *dev = (opl_t *)priv; - timer_over(dev, 1); + timer_tick(dev, 1); } static uint8_t opl_read(opl_t *dev, uint16_t port) { - if (! (port & 1)) - return((dev->status & dev->status_mask) | (dev->is_opl3 ? 0x00 : 0x06)); + uint8_t ret = 0xff; - if (dev->is_opl3 && ((port & 0x03) == 0x03)) - return(0x00); + if ((port & 0x0003) == 0x0000) { + ret = ((dev->status & dev->status_mask) | (dev->is_opl3 ? 0x00 : 0x06)); + if (dev->status & dev->status_mask) + ret |= STATUS_TIMER_ALL; + } - return(dev->is_opl3 ? 0x00 : 0xff); + return ret; } static void opl_write(opl_t *dev, uint16_t port, uint8_t val) { - if (! (port & 1)) { + if ((port & 0x0001) == 0x0001) { + nuked_write_reg_buffered(dev->opl, dev->port, val); + + switch (dev->port) { + case 0x02: /* Timer 1 */ + dev->timer_count[0] = val; + opl_log("Timer 0 count now: %i\n", dev->timer_count[0]); + break; + + case 0x03: /* Timer 2 */ + dev->timer_count[1] = val; + opl_log("Timer 1 count now: %i\n", dev->timer_count[1]); + break; + + case 0x04: /* Timer control */ + if (val & CTRL_IRQ_RESET) { + opl_log("Resetting timer status...\n"); + dev->status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2); + } else { + timer_control(dev, 0, val & CTRL_TIMER1_CTRL); + timer_control(dev, 1, val & CTRL_TIMER2_CTRL); + dev->timer_ctrl = val; + dev->status_mask = (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK) & ~(val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)); + opl_log("Status mask now %02X (val = %02X)\n", dev->status_mask, val); + } + break; + } + } else { dev->port = nuked_write_addr(dev->opl, port, val) & 0x01ff; if (! dev->is_opl3) @@ -125,40 +185,6 @@ opl_write(opl_t *dev, uint16_t port, uint8_t val) return; } - - nuked_write_reg_buffered(dev->opl, dev->port, val); - - switch (dev->port) { - case 0x02: // timer 1 - dev->timer[0] = 256 - val; - break; - - case 0x03: // timer 2 - dev->timer[1] = 256 - val; - break; - - case 0x04: // timer control - if (val & CTRL_IRQ_RESET) { - dev->status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2); - status_update(dev); - return; - } - if ((val ^ dev->timer_ctrl) & CTRL_TIMER1_CTRL) { - if (val & CTRL_TIMER1_CTRL) - timer_set(dev, 0, dev->timer[0] * 4); - else - timer_set(dev, 0, 0); - } - if ((val ^ dev->timer_ctrl) & CTRL_TIMER2_CTRL) { - if (val & CTRL_TIMER2_CTRL) - timer_set(dev, 1, dev->timer[1] * 16); - else - timer_set(dev, 1, 0); - } - dev->status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80; - dev->timer_ctrl = val; - break; - } } diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 0a5124913..46dbbf071 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -1079,7 +1079,7 @@ nuked_write_addr(void *priv, uint16_t port, uint8_t val) uint16_t addr; addr = val; - if ((port & 0x0002) && (addr == 0x0005 || dev->newm)) + if ((port & 0x0002) && ((addr == 0x0005) || dev->newm)) addr |= 0x0100; return(addr); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index e42317536..5f38085a2 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -106,7 +106,7 @@ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { int32_t out = 0; if (sb->opl_enabled) - out = ((sb->opl.buffer[c] * (sb->opl_emu ? 47000 : 51000)) >> 16); + 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; @@ -140,7 +140,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p) int32_t out = 0; if (sb->opl_enabled) - out = ((((sb->opl.buffer[c] * mixer->fm) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + 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 */ @@ -188,11 +188,11 @@ void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) * Each chip stores data into the LEFT channel * only (no sample alternating.) */ - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); - out_r = ((((sb->opl2.buffer[c] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + 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) * (sb->opl_emu ? 47000 : 51000)) >> 15); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + 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); } } @@ -244,8 +244,8 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) 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) * (sb->opl_emu ? 47000 : 51000)) >> 15); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); + 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); } /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ @@ -328,8 +328,8 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) int c_emu8k = (((c/2) * 44100) / 48000)*2; if (sb->opl_enabled) { - out_l = ((((sb->opl.buffer[c] * mixer->fm_l) >> 15) * (sb->opl_emu ? 47000 : 51000)) >> 16); - out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 15) * (sb->opl_emu ? 47000 : 51000)) >> 16); + 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); } out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 15); @@ -636,6 +636,9 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) { /* Reset */ /* Changed defaults from -14dB to 0dB*/ + mixer->regs[0x0E]=0x02; + sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0E] & 2); + mixer->regs[0x30]=31 << 3; mixer->regs[0x31]=31 << 3; mixer->regs[0x32]=31 << 3; @@ -826,6 +829,9 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) 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; From 24926d4b2f8c93ceba3f8291b6461fd7473e3f5b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 26 Jul 2020 01:53:46 +0200 Subject: [PATCH 2/3] Removed a temporary thing from sound/snd_sb.c, removed the unused opl_emu variable from the Sound Blaster struct, and added the AMI S3 86c924 with its ICS2494AN-305 clock chip. --- src/include/86box/snd_sb.h | 2 - src/include/86box/vid_svga.h | 7 +- src/include/86box/video.h | 1 + src/sound/snd_sb.c | 3 - src/video/vid_ics2494.c | 114 ++++++++++++++++++++++++++++ src/video/vid_s3.c | 142 +++++++++++++++++++++++------------ src/video/vid_table.c | 1 + src/win/Makefile.mingw | 3 +- 8 files changed, 214 insertions(+), 59 deletions(-) create mode 100644 src/video/vid_ics2494.c diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 2c8e0ce21..f3180da91 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -126,8 +126,6 @@ typedef struct sb_t int pos; uint8_t pos_regs[8]; - - int opl_emu; } sb_t; extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p); diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index d63af24c9..7bc35bcdc 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -13,8 +13,8 @@ * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ @@ -222,6 +222,8 @@ extern float icd2061_getclock(int clock, void *p); #define ics9161_write icd2061_write #define ics9161_getclock icd2061_getclock +extern float ics2494_getclock(int clock, void *p); + extern void ics2595_write(void *p, int strobe, int dat); extern double ics2595_getclock(void *p); extern void ics2595_setclock(void *p, double clock); @@ -255,6 +257,7 @@ extern const device_t bt485_ramdac_device; extern const device_t att20c505_ramdac_device; extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; +extern const device_t ics2494an_305_device; extern const device_t ics2595_device; extern const device_t icd2061_device; extern const device_t ics9161_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 27c40ac06..639905d01 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -298,6 +298,7 @@ extern const device_t paradise_wd90c30_device; /* S3 9XX/8XX/Vision/Trio */ extern const device_t s3_orchid_86c911_isa_device; +extern const device_t s3_ami_86c924_isa_device; extern const device_t s3_metheus_premier_86c928_isa_device; extern const device_t s3_metheus_premier_86c928_vlb_device; extern const device_t s3_v7mirage_86c801_isa_device; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 5f38085a2..68709904d 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -636,9 +636,6 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) { /* Reset */ /* Changed defaults from -14dB to 0dB*/ - mixer->regs[0x0E]=0x02; - sb_dsp_set_stereo(&sb->dsp, mixer->regs[0x0E] & 2); - mixer->regs[0x30]=31 << 3; mixer->regs[0x31]=31 << 3; mixer->regs[0x32]=31 << 3; diff --git a/src/video/vid_ics2494.c b/src/video/vid_ics2494.c new file mode 100644 index 000000000..f6f72cf05 --- /dev/null +++ b/src/video/vid_ics2494.c @@ -0,0 +1,114 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ICS2494 clock generator emulation. + * + * Used by the AMI S3 924. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> + + +typedef struct ics2494_t +{ + float freq[16]; +} ics2494_t; + + +#ifdef ENABLE_ics2494_LOG +int ics2494_do_log = ENABLE_ics2494_LOG; + + +static void +ics2494_log(const char *fmt, ...) +{ + va_list ap; + + if (ics2494_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ics2494_log(fmt, ...) +#endif + + +float +ics2494_getclock(int clock, void *p) +{ + ics2494_t *ics2494 = (ics2494_t *) p; + + if (clock > 16) + clock = 16; + + return ics2494->freq[clock]; +} + + +static void * +ics2494_init(const device_t *info) +{ + ics2494_t *ics2494 = (ics2494_t *) malloc(sizeof(ics2494_t)); + memset(ics2494, 0, sizeof(ics2494_t)); + + switch (info->local) { + case 305: + /* ICS2494A(N)-205 for S3 86C924 */ + ics2494->freq[0x0] = 25175000.0; + ics2494->freq[0x1] = 28322000.0; + ics2494->freq[0x2] = 40000000.0; + ics2494->freq[0x3] = 0.0; + ics2494->freq[0x4] = 50000000.0; + ics2494->freq[0x5] = 77000000.0; + ics2494->freq[0x6] = 36000000.0; + ics2494->freq[0x7] = 44889000.0; + ics2494->freq[0x8] = 130000000.0; + ics2494->freq[0x9] = 120000000.0; + ics2494->freq[0xa] = 80000000.0; + ics2494->freq[0xb] = 31500000.0; + ics2494->freq[0xc] = 110000000.0; + ics2494->freq[0xd] = 65000000.0; + ics2494->freq[0xe] = 75000000.0; + ics2494->freq[0xf] = 94500000.0; + break; + } + + return ics2494; +} + + +static void +ics2494_close(void *priv) +{ + ics2494_t *ics2494 = (ics2494_t *) priv; + + if (ics2494) + free(ics2494); +} + + +const device_t ics2494an_305_device = +{ + "ICS2494AN-305 Clock Generator", + 0, 305, + ics2494_init, ics2494_close, + NULL, NULL, NULL, NULL +}; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index edefbf818..d2bd91a85 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -35,6 +35,7 @@ #include "cpu.h" #define ROM_ORCHID_86C911 L"roms/video/s3/BIOS.BIN" +#define ROM_AMI_86C924 L"roms/video/s3/S3924AMI.BIN" #define ROM_METHEUS_86C928 L"roms/video/s3/928.vbi" #define ROM_V7MIRAGE_86C801 L"roms/video/s3/v7mirage.vbi" #define ROM_PHOENIX_86C805 L"roms/video/s3/805.vbi" @@ -59,21 +60,29 @@ enum S3_V7MIRAGE_86C801, S3_PHOENIX_86C805, S3_ORCHID_86C911, - S3_METHEUS_86C928 + S3_METHEUS_86C928, + S3_AMI_86C924 }; + enum { - S3_86C801, + S3_86C911 = 0x00, + S3_86C924, + S3_86C928 = 0x04, + S3_86C801 = 0x06, S3_86C805, - S3_86C928, - S3_86C911, + S3_VISION964 = 0x08, S3_VISION864, - S3_VISION964, - S3_TRIO32, + S3_TRIO32 = 0x18, S3_TRIO64 }; +#define S3_86C80X 0x02 +#define S3_86C928_80X 0x04 +#define S3_TRIO 0x10 + + static video_timings_t timing_s3_86c911 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_86c801 = {VIDEO_ISA, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_86c805 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; @@ -282,7 +291,7 @@ int s3_cpu_src(s3_t *s3) if (!(s3->accel.cmd & 0x100)) return 0; - if (s3->chip > S3_86C911) + if (s3->chip >= S3_VISION964) return 1; if (s3->accel.cmd & 1) @@ -296,7 +305,7 @@ int s3_cpu_dest(s3_t *s3) if (!(s3->accel.cmd & 0x100)) return 0; - if (s3->chip > S3_86C911) + if (s3->chip >= S3_VISION964) return 0; if (s3->accel.cmd & 1) @@ -1094,7 +1103,7 @@ void s3_hwcursor_draw(svga_t *svga, int displine) break; default: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + if (s3->chip & S3_TRIO) { fg = svga->pallook[s3->hwc_fg_col & 0xff]; bg = svga->pallook[s3->hwc_bg_col & 0xff]; @@ -1283,7 +1292,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: - if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); } @@ -1314,17 +1323,17 @@ void s3_out(uint16_t addr, uint8_t val, void *p) rs2 = !!(svga->crtc[0x43] & 0x02); else rs2 = (svga->crtc[0x55] & 0x01); - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + if (s3->chip & S3_TRIO) svga_out(addr, val, svga); - else if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) { + else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) rs3 = !!(svga->crtc[0x55] & 0x02); else rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) att49x_ramdac_out(addr, val, svga->ramdac, svga); - else if (s3->chip == S3_86C911) + else if (s3->chip < S3_86C928) sc1148x_ramdac_out(addr, val, svga->ramdac, svga); else sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga); @@ -1359,7 +1368,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) case 0x50: mask = 0xc0; - if (s3->chip > S3_86C805) + if (s3->chip != S3_86C801) mask |= 0x01; switch (svga->crtc[0x50] & mask) { @@ -1373,8 +1382,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) s3->bpp = (svga->crtc[0x50] >> 4) & 3; break; case 0x69: - if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && - (s3->chip != S3_86C911) && (s3->chip != S3_86C928)) + if (s3->chip >= S3_VISION964) s3->ma_ext = val & 0x1f; break; @@ -1386,7 +1394,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: - if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + if (s3->chip & S3_86C80X) s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); else s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); @@ -1394,14 +1402,13 @@ void s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; - if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + if (s3->chip & S3_86C80X) s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); else s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); break; case 0x6a: - if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && - (s3->chip != S3_86C911) && (s3->chip != S3_86C928)) { + if (s3->chip >= S3_VISION964) { s3->bank = val; if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; @@ -1429,9 +1436,9 @@ void s3_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.xoff = svga->crtc[0x4e] & 63; svga->hwcursor.yoff = svga->crtc[0x4f] & 63; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32) + if ((s3->chip & S3_TRIO) && svga->bpp == 32) svga->hwcursor.x <<= 1; - else if ((s3->chip == S3_86C801 || s3->chip == S3_86C805 || s3->chip == S3_86C928) && (svga->bpp == 15 || svga->bpp == 16)) + else if ((s3->chip & S3_86C928_80X) && (svga->bpp == 15 || svga->bpp == 16)) svga->hwcursor.x >>= 1; break; @@ -1485,15 +1492,14 @@ void s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x42: - if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } break; case 0x43: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805 || - s3->chip == S3_86C911 || s3->chip == S3_86C928) { + if (s3->chip < S3_VISION964) { s3_io_remove_alt(s3); s3->translate = !!(svga->crtc[0x43] & 0x10); s3_io_set_alt(s3); @@ -1501,7 +1507,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x67: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + if (s3->chip & S3_TRIO) { switch (val >> 4) { @@ -1545,7 +1551,7 @@ uint8_t s3_in(uint16_t addr, void *p) break; case 0x3c2: - if (s3->chip == S3_86C911) + if (s3->chip <= S3_86C924) return svga_in(addr, svga) | 0x10; break; @@ -1556,14 +1562,14 @@ uint8_t s3_in(uint16_t addr, void *p) case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + if (s3->chip & S3_TRIO) return svga_in(addr, svga); - else if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) { + else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + } else if (s3->chip & S3_86C80X) return att49x_ramdac_in(addr, svga->ramdac, svga); - else if (s3->chip == S3_86C911) + else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, svga->ramdac, svga); else return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); @@ -1624,12 +1630,12 @@ void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; - if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) bt48x_recalctimings(svga->ramdac, svga); else svga->interlace = svga->crtc[0x42] & 0x20; - if ((((svga->miscout >> 2) & 3) == 3) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64)) + if ((((svga->miscout >> 2) & 3) == 3) && !(s3->chip & S3_TRIO)) clk_sel = svga->crtc[0x42] & 0x0f; svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock(clk_sel, svga->clock_gen); @@ -1651,7 +1657,7 @@ void s3_recalctimings(svga_t *svga) break; case 15: svga->render = svga_render_15bpp_highres; - if (s3->chip != S3_VISION964 && s3->chip != S3_86C801) + if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; @@ -1661,7 +1667,7 @@ void s3_recalctimings(svga_t *svga) break; case 16: svga->render = svga_render_16bpp_highres; - if (s3->chip != S3_VISION964 && s3->chip != S3_86C801) + if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; @@ -1670,15 +1676,15 @@ void s3_recalctimings(svga_t *svga) } break; case 24: - svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_86C801 && s3->chip != S3_86C805 && s3->chip != S3_86C928) + svga->render = svga_render_24bpp_highres; + if (!(s3->chip & S3_86C928_80X)) svga->hdisp /= 3; else svga->hdisp = (svga->hdisp * 2) / 3; break; case 32: svga->render = svga_render_32bpp_highres; - if ((s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_86C928)) + if (!(s3->chip & S3_TRIO) && (s3->chip != S3_VISION964) && (s3->chip != S3_86C928)) svga->hdisp /= 4; break; } @@ -1730,8 +1736,7 @@ void s3_updatemapping(s3_t *s3) mem_mapping_disable(&svga->mapping); s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || - (s3->chip == S3_86C928)) { + if (s3->chip & S3_86C928_80X) { if (s3->vlb) s3->linear_base &= 0x03ffffff; else @@ -1808,8 +1813,7 @@ int s3_enable_fifo(s3_t *s3) #if 0 svga_t *svga = &s3->svga; - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) + if (s3->chip >= S3_VISION964) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); @@ -1847,7 +1851,7 @@ void s3_accel_out(uint16_t port, uint8_t val, void *p) break; case 0x4948: case 0x4ae8: s3->accel.advfunc_cntl = val; - if (s3->chip != S3_86C911) /*S3 911/924 doesn't do MMIO*/ + if (s3->chip >= S3_86C928) /*S3 911/924 doesn't do MMIO*/ s3_updatemapping(s3); break; } @@ -1932,7 +1936,7 @@ uint8_t s3_accel_in(uint16_t port, void *p) temp = 0; /* FIFO empty */ if (!s3->blitter_busy) wake_fifo_thread(s3); - if (FIFO_FULL && s3->chip >= S3_VISION864) + if (FIFO_FULL && (s3->chip >= S3_VISION864)) temp = 0xff; /*FIFO full*/ return temp; /*FIFO empty*/ case 0x9949: case 0x9ae9: @@ -2168,7 +2172,7 @@ uint16_t s3_accel_read_w(uint32_t addr, void *p) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) { - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32)) { s3_accel_start(8, 1, 0xff, 0, s3); s3_accel_start(8, 1, 0xff, 0, s3); @@ -2214,7 +2218,7 @@ uint32_t s3_accel_read_l(uint32_t addr, void *p) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) { - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32)) { s3_accel_start(8, 1, 0xff, 0, s3); s3_accel_start(8, 1, 0xff, 0, s3); @@ -3203,12 +3207,12 @@ uint8_t s3_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + if (s3->chip & S3_TRIO) return 0x00; /*Supports VGA interface*/ else return 0x01; case 0x0b: - if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + if (s3->chip & S3_TRIO) return 0x03; else return 0x00; @@ -3302,6 +3306,11 @@ static void *s3_init(const device_t *info) chip = S3_86C911; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); break; + case S3_AMI_86C924: + bios_fn = ROM_AMI_86C924; + chip = S3_86C924; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c911); + break; case S3_V7MIRAGE_86C801: bios_fn = ROM_V7MIRAGE_86C801; chip = S3_86C801; @@ -3446,7 +3455,7 @@ static void *s3_init(const device_t *info) if (chip == S3_VISION964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; - if (chip >= S3_VISION864) { + if (chip >= S3_VISION964) { switch (vram) { case 0: /* 512 kB */ svga->vram_mask = (1 << 19) - 1; @@ -3520,7 +3529,21 @@ static void *s3_init(const device_t *info) svga->clock_gen = device_add(&av9194_device); svga->getclock = av9194_getclock; break; + + case S3_AMI_86C924: + svga->decode_mask = (1 << 20) - 1; + stepping = 0x82; /*86C911A/86C924*/ + s3->id = stepping; + s3->id_ext = stepping; + s3->id_ext_pci = 0; + s3->packed_mmio = 0; + s3->width = 1024; + svga->ramdac = device_add(&sc11487_ramdac_device); + svga->clock_gen = device_add(&ics2494an_305_device); + svga->getclock = ics2494_getclock; + break; + case S3_V7MIRAGE_86C801: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ @@ -3632,6 +3655,11 @@ static int s3_orchid_86c911_available(void) return rom_present(ROM_ORCHID_86C911); } +static int s3_ami_86c924_available(void) +{ + return rom_present(ROM_AMI_86C924); +} + static int s3_v7mirage_86c801_available(void) { return rom_present(ROM_V7MIRAGE_86C801); @@ -3838,6 +3866,20 @@ const device_t s3_orchid_86c911_isa_device = s3_orchid_86c911_config }; +const device_t s3_ami_86c924_isa_device = +{ + "AMI S3 86c924 ISA", + DEVICE_AT | DEVICE_ISA, + S3_AMI_86C924, + s3_init, + s3_close, + NULL, + s3_ami_86c924_available, + s3_speed_changed, + s3_force_redraw, + s3_orchid_86c911_config +}; + const device_t s3_v7mirage_86c801_isa_device = { "SPEA V7 Mirage (S3 86c801) ISA", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index acff552ea..dd47d771a 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -54,6 +54,7 @@ static const VIDEO_CARD video_cards[] = { { "None", "none", NULL }, { "Internal", "internal", NULL }, + { "[ISA] AMI S3 86c924", "ami_s3_924", &s3_ami_86c924_isa_device }, { "[ISA] ATI EGA Wonder 800+", "egawonder800", &atiega_device }, { "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device }, { "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index b30c0c10e..499197c68 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -752,8 +752,7 @@ VIDOBJ := video.o \ vid_ati18800.o vid_ati28800.o \ vid_ati_mach64.o vid_ati68860_ramdac.o \ vid_bt48x_ramdac.o \ - vid_av9194.o \ - vid_icd2061.o vid_ics2595.o \ + vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ vid_cl54xx.o \ vid_et4000.o vid_sc1148x_ramdac.o \ vid_sc1502x_ramdac.o \ From 797af21ad9f710998a9d58e1a8ab4646769eaf47 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 26 Jul 2020 02:35:41 +0200 Subject: [PATCH 3/3] Finished the sound/snd_opl.c rewrite. --- src/include/86box/snd_opl.h | 13 ++---- src/sound/snd_opl.c | 93 ++++++++++++++++++------------------- src/sound/snd_opl_nuked.c | 2 - 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 38077e1d3..f6e533e4a 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -8,16 +8,11 @@ * * Definitions for the OPL interface. * - * Version: @(#)snd_opl.h 1.0.3 2020/07/15 - * * Authors: Fred N. van Kempen, * Miran Grca, - * TheCollector1995, - * Sarah Walker, * * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #ifndef SOUND_OPL_H # define SOUND_OPL_H @@ -32,12 +27,10 @@ typedef struct { #else void *opl; #endif - int8_t is_opl3, do_cycles; + int8_t flags, pad; uint16_t port; - uint8_t status; - uint8_t status_mask; - uint8_t timer_ctrl; + uint8_t status, timer_ctrl; uint16_t timer_count[2], timer_cur_count[2]; diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 7fbfd3fc6..488acdc35 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -14,19 +14,17 @@ * * Authors: Fred N. van Kempen, * Miran Grca, - * TheCollector1995, - * Sarah Walker, * * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ -#include +#include #include -#include +#include #include +#include #include -#define dbglog sound_card_log +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> #include "cpu.h" @@ -37,17 +35,24 @@ enum { - STATUS_TIMER_1 = 0x40, - STATUS_TIMER_2 = 0x20, - STATUS_TIMER_ALL = 0x80 + FLAG_CYCLES = 0x02, + FLAG_OPL3 = 0x01 }; enum { - CTRL_IRQ_RESET = 0x80, - CTRL_TIMER1_MASK = 0x40, - CTRL_TIMER2_MASK = 0x20, - CTRL_TIMER2_CTRL = 0x02, - CTRL_TIMER1_CTRL = 0x01 + STAT_TMR_OVER = 0x60, + STAT_TMR1_OVER = 0x40, + STAT_TMR2_OVER = 0x20, + STAT_TMR_ANY = 0x80 +}; + +enum { + CTRL_RESET = 0x80, + CTRL_TMR_MASK = 0x60, + CTRL_TMR1_MASK = 0x40, + CTRL_TMR2_MASK = 0x20, + CTRL_TMR2_START = 0x02, + CTRL_TMR1_START = 0x01 }; @@ -71,21 +76,6 @@ opl_log(const char *fmt, ...) #endif -static void -timer_over(opl_t *dev, int tmr) -{ - opl_log("Count wrapped around to zero, reloading timer %i...\n", tmr); - - if (tmr == 1) { - dev->status |= STATUS_TIMER_2; - dev->timer_cur_count[1] = dev->timer_count[1]; - } else { - dev->status |= STATUS_TIMER_1; - dev->timer_cur_count[0] = dev->timer_count[0]; - } -} - - static void timer_tick(opl_t *dev, int tmr) { @@ -93,8 +83,12 @@ timer_tick(opl_t *dev, int tmr) opl_log("Ticking timer %i, count now %02X...\n", tmr, dev->timer_cur_count[tmr]); - if (dev->timer_cur_count[tmr] == 0x00) - timer_over(dev, tmr); + if (dev->timer_cur_count[tmr] == 0x00) { + dev->status |= ((STAT_TMR1_OVER >> tmr) & ~dev->timer_ctrl); + dev->timer_cur_count[tmr] = dev->timer_count[tmr]; + + opl_log("Count wrapped around to zero, reloading timer %i (%02X), status = %02X...\n", tmr, (STAT_TMR1_OVER >> tmr), dev->status); + } timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0); } @@ -138,9 +132,9 @@ opl_read(opl_t *dev, uint16_t port) uint8_t ret = 0xff; if ((port & 0x0003) == 0x0000) { - ret = ((dev->status & dev->status_mask) | (dev->is_opl3 ? 0x00 : 0x06)); - if (dev->status & dev->status_mask) - ret |= STATUS_TIMER_ALL; + ret = dev->status; + if (dev->status & STAT_TMR_OVER) + ret |= STAT_TMR_ANY; } return ret; @@ -165,22 +159,21 @@ opl_write(opl_t *dev, uint16_t port, uint8_t val) break; case 0x04: /* Timer control */ - if (val & CTRL_IRQ_RESET) { + if (val & CTRL_RESET) { opl_log("Resetting timer status...\n"); - dev->status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2); + dev->status &= ~STAT_TMR_OVER; } else { - timer_control(dev, 0, val & CTRL_TIMER1_CTRL); - timer_control(dev, 1, val & CTRL_TIMER2_CTRL); + timer_control(dev, 0, val & CTRL_TMR1_START); + timer_control(dev, 1, val & CTRL_TMR2_START); dev->timer_ctrl = val; - dev->status_mask = (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK) & ~(val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)); - opl_log("Status mask now %02X (val = %02X)\n", dev->status_mask, val); + opl_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val); } break; } } else { dev->port = nuked_write_addr(dev->opl, port, val) & 0x01ff; - if (! dev->is_opl3) + if (!(dev->flags & FLAG_OPL3)) dev->port &= 0x00ff; return; @@ -191,7 +184,10 @@ opl_write(opl_t *dev, uint16_t port, uint8_t val) void opl_set_do_cycles(opl_t *dev, int8_t do_cycles) { - dev->do_cycles = do_cycles; + if (do_cycles) + dev->flags |= FLAG_CYCLES; + else + dev->flags &= ~FLAG_CYCLES; } @@ -200,8 +196,11 @@ opl_init(opl_t *dev, int is_opl3) { memset(dev, 0x00, sizeof(opl_t)); - dev->is_opl3 = is_opl3; - dev->do_cycles = 1; + dev->flags = FLAG_CYCLES; + if (is_opl3) + dev->flags |= FLAG_OPL3; + else + dev->status = 0x06; /* Create a NukedOPL object. */ dev->opl = nuked_init(48000); @@ -227,7 +226,7 @@ opl2_read(uint16_t port, void *priv) { opl_t *dev = (opl_t *)priv; - if (dev->do_cycles) + if (dev->flags & FLAG_CYCLES) sub_cycles((int) (isa_timing * 8)); opl2_update(dev); @@ -276,7 +275,7 @@ opl3_read(uint16_t port, void *priv) { opl_t *dev = (opl_t *)priv; - if (dev->do_cycles) + if (dev->flags & FLAG_CYCLES) sub_cycles((int)(isa_timing * 8)); opl3_update(dev); diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 46dbbf071..5bde0d2dd 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -31,12 +31,10 @@ * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * Alexey Khokholov (Nuke.YKT) * * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2016-2020 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) */ #include