From eba4ca376e40748252c50dff4bd55a240ec79bf0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 30 Sep 2018 20:29:44 +0200 Subject: [PATCH] Added the Diamond Stealth 64 VRAM (S3 Vision964) and its Brooktree BT485 RAM DAC; Removed the ExpertColor S3 Vision868 card; Rewritten the ICD2061 clock chip and moved the Diamond Stealth 32 back to the main branch as it's now fixed; Fixed the Y offset of the 64x64 hardware cursor of the Cirrus Logic cards. --- src/video/vid_bt485_ramdac.c | 453 +-- src/video/vid_bt485_ramdac.h | 22 +- src/video/vid_cl54xx.c | 3 +- src/video/vid_et4000w32.c | 32 +- src/video/vid_et4000w32.h | 2 - src/video/vid_icd2061.c | 141 +- src/video/vid_icd2061.h | 36 +- src/video/vid_s3.c | 5213 +++++++++++++++++----------------- src/video/vid_s3.h | 4 +- src/video/vid_table.c | 10 +- src/win/Makefile.mingw | 16 +- 11 files changed, 3101 insertions(+), 2831 deletions(-) diff --git a/src/video/vid_bt485_ramdac.c b/src/video/vid_bt485_ramdac.c index 80087044d..c47598eab 100644 --- a/src/video/vid_bt485_ramdac.c +++ b/src/video/vid_bt485_ramdac.c @@ -8,16 +8,14 @@ * * Brooktree BT485 true colour RAMDAC emulation. * - * Currently only a dummy stub for logging and passing output - * to the generic SVGA handler. * - * Version: @(#)vid_bt485_ramdac.c 1.0.2 2017/11/04 + * Version: @(#)vid_bt485_ramdac.c 1.0.4 2018/09/30 * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, + * TheCollector1995, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. + * Copyright 2018 TheCollector1995. */ #include #include @@ -30,163 +28,294 @@ #include "vid_bt485_ramdac.h" -int bt485_get_clock_divider(bt485_ramdac_t *ramdac) +void +bt485_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga) { - return 1; /* Will be implemented later. */ + uint32_t o32; + uint8_t *cd; + + switch (addr) { + case 0x3C6: + if (rs2) { + if (rs3) { /*REG0E, Hardware Cursor Y-position*/ + ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; + svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; + /* pclog("BT485 0E Y=%d\n", ramdac->hwc_y); */ + break; + } else { /*REG06, Command Reg 0*/ + ramdac->cr0 = val; + svga->ramdac_type = (val & 0x01) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + } + } else { + if (rs3) { /*REG0A*/ + switch (ramdac->set_reg0a) { + case 0: /*Status, read-only*/ + break; + + case 1: /*Command Reg 3*/ + ramdac->cr3 = val; + svga->hwcursor.xsize = svga->hwcursor.ysize = (val & 4) ? 64 : 32; + svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; + svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; + svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; + if (svga->hwcursor.xsize == 64) + svga->dac_pos = (svga->dac_pos & 0x00ff) | ((val & 0x03) << 8); + svga_recalctimings(svga); + break; + } + break; + } else { /*REG02*/ + svga_out(addr, val, svga); + break; + } + } + break; + + case 0x3C7: + if (!rs2 && !rs3) { /*REG03*/ + svga_out(addr, val, svga); + break; + } else if (rs2 && !rs3) { /*REG07, Cursor/Overscan Read Address*/ + svga->dac_read = val; + svga->dac_pos = 0; + break; + } else if (!rs2 && rs3) { /*REG0B, Cursor Ram Data*/ + if (svga->hwcursor.xsize == 64) + cd = (uint8_t *) ramdac->cursor64_data; + else + cd = (uint8_t *) ramdac->cursor32_data; + + cd[svga->dac_pos] = val; + svga->dac_pos++; + if (svga->hwcursor.xsize == 32) + svga->dac_pos &= 0x00ff; + else + svga->dac_pos &= 0x03ff; + break; + } else { /*REG0F, Hardware Cursor Y-position*/ + ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); + svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; + /* pclog("BT485 0F Y=%d\n", ramdac->hwc_y); */ + break; + } + break; + + case 0x3C8: + ramdac->set_reg0a = (ramdac->cr0 & 0x80) ? 1 : 0; + if (rs2) { + if (rs3) { /*REG0C, Hardware Cursor X-position*/ + ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; + svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; + /* pclog("BT485 0C X=%d\n", ramdac->hwc_x); */ + break; + } + else { /*REG04, Cursor/Overscan Write Address*/ + svga->dac_write = val; + svga->dac_read = val - 1; + svga->dac_pos = 0; + break; + } + } else { + if (rs3) { /*REG08, Command Reg 1*/ + ramdac->cr1 = val; + switch (val >> 5) { + case 0: + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) + svga->bpp = 32; + else + svga->bpp = 8; + break; + + case 1: + if (ramdac->cr1 & 8) + svga->bpp = 16; + else + svga->bpp = 15; + break; + + case 2: + svga->bpp = 8; + break; + + case 3: + svga->bpp = 4; + break; + } + svga_recalctimings(svga); + break; + } + else { /*REG00*/ + svga_out(addr, val, svga); + break; + } + } + break; + + case 0x3C9: + if (rs2) { + if (rs3) { /*REG0D, Hardware Cursor X-position*/ + ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); + svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; + /* pclog("BT485 0D X=%d\n", ramdac->hwc_x); */ + break; + } else { /*REG05, Cursor/Overscan Data*/ + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + case 2: + ramdac->extpal[svga->dac_write].r = svga->dac_r; + ramdac->extpal[svga->dac_write].g = svga->dac_g; + ramdac->extpal[svga->dac_write].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->extpallook[svga->dac_write & 3] = makecol32(ramdac->extpal[svga->dac_write].r & 0x3f, ramdac->extpal[svga->dac_write].g & 0x3f, ramdac->extpal[svga->dac_write].b & 0x3f); + else + ramdac->extpallook[svga->dac_write & 3] = makecol32(video_6to8[ramdac->extpal[svga->dac_write].r & 0x3f], video_6to8[ramdac->extpal[svga->dac_write].g & 0x3f], video_6to8[ramdac->extpal[svga->dac_write].b & 0x3f]); + + if ((svga->crtc[0x33] & 0x40) && ((svga->dac_write & 3) == 0)) { + o32 = svga->overscan_color; + svga->overscan_color = ramdac->extpallook[0]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); + } + svga->dac_write = (svga->dac_write + 1) & 15; + svga->dac_pos = 0; + break; + } + break; + } + } + else { + if (rs3) { /*REG09, Command Reg 2*/ + ramdac->cr2 = val; + svga->hwcursor.ena = ramdac->cr2 & 0x03; + svga_recalctimings(svga); + break; + } else { /*REG01*/ + svga_out(addr, val, svga); + break; + } + } + break; + } + return; } -void bt485_set_rs2(uint8_t rs2, bt485_ramdac_t *ramdac) + +uint8_t +bt485_ramdac_in(uint16_t addr, int rs2, int rs3, bt485_ramdac_t *ramdac, svga_t *svga) { - ramdac->rs2 = rs2 ? 1 : 0; -} - -void bt485_set_rs3(uint8_t rs3, bt485_ramdac_t *ramdac) -{ - ramdac->rs3 = rs3 ? 1 : 0; -} - -void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga) -{ -// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); - uint8_t reg = addr & 3; - reg |= (ramdac->rs2 ? 4 : 0); - reg |= (ramdac->rs3 ? 8 : 0); - pclog("BT485 RAMDAC: Writing %02X to register %02X\n", val, reg); - svga_out(addr, val, svga); - return; - - switch (addr) - { - case 0x3C6: - if (val == 0xff) - { - ramdac->rs2 = 0; - ramdac->magic_count = 0; - break; - } - if (ramdac->magic_count < 4) break; - if (ramdac->magic_count == 4) - { - ramdac->command = val; -// pclog("RAMDAC command reg now %02X\n", val); - switch (val >> 4) - { - case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; - case 0x4: case 0xe: svga->bpp = 24; break; - case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; - case 0x7: svga->bpp = 32; break; - - case 0: case 1: default: svga->bpp = 8; break; - } - svga_recalctimings(svga); - } - //ramdac->magic_count = 0; - break; - - case 0x3C7: - ramdac->magic_count = 0; - if (ramdac->rs2) - ramdac->rindex = val; - break; - case 0x3C8: - ramdac->magic_count = 0; - if (ramdac->rs2) - ramdac->windex = val; - break; - case 0x3C9: - ramdac->magic_count = 0; - if (ramdac->rs2) - { - if (!ramdac->reg_ff) ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0xff00) | val; - else ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0x00ff) | (val << 8); - ramdac->reg_ff = !ramdac->reg_ff; -// pclog("RAMDAC reg %02X now %04X\n", ramdac->windex, ramdac->regs[ramdac->windex]); - if (!ramdac->reg_ff) ramdac->windex++; - } - break; - } - svga_out(addr, val, svga); -} - -uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t temp; -// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, ramdac->rs2); - uint8_t reg = addr & 3; - reg |= (ramdac->rs2 ? 4 : 0); - reg |= (ramdac->rs3 ? 8 : 0); - pclog("BT485 RAMDAC: Reading register %02X\n", reg); - return svga_in(addr, svga); - - switch (addr) - { - case 0x3C6: - ramdac->reg_ff = 0; - if (ramdac->magic_count < 5) - ramdac->magic_count++; - if (ramdac->magic_count == 4) - { - temp = 0x70; /*SDAC ID*/ - ramdac->rs2 = 1; - } - if (ramdac->magic_count == 5) - { - temp = ramdac->command; - ramdac->magic_count = 0; - } - return temp; - case 0x3C7: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) return ramdac->rindex; - break; - case 0x3C8: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) return ramdac->windex; - break; - case 0x3C9: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) - { - if (!ramdac->reg_ff) temp = ramdac->regs[ramdac->rindex] & 0xff; - else temp = ramdac->regs[ramdac->rindex] >> 8; - ramdac->reg_ff = !ramdac->reg_ff; - if (!ramdac->reg_ff) - { - ramdac->rindex++; - ramdac->magic_count = 0; - } - return temp; - } - break; - } - return svga_in(addr, svga); -} - -float bt485_getclock(int clock, void *p) -{ - bt485_ramdac_t *ramdac = (bt485_ramdac_t *)p; - float t; - int m, n1, n2; -// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]); - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - m = (ramdac->regs[clock] & 0x7f) + 2; - n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; - n2 = ((ramdac->regs[clock] >> 13) & 0x07); - t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); -// pclog("BT485 clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2); - return t; + uint8_t temp = 0xff; + uint8_t *cd; + + switch (addr) { + case 0x3C6: + if (rs2) { + if (rs3) /*REG0E, Hardware Cursor Y-position, write only*/ + return 0xff; + else /*REG06, Command Reg 0*/ + return ramdac->cr0; + } else { + if (rs3) { /*REG0A*/ + switch (ramdac->set_reg0a) { + case 0: /*Status, read-only*/ + return 0x0b; /*Bt485*/ + + case 1: /*Command Reg 3*/ + if (ramdac->cr2 & 4) { + if (ramdac->cr3 & 2) + temp = 0xa9; + else + temp = 0xa8; + } else + temp = ramdac->cr3; + temp &= 0xfc; + if (svga->hwcursor.xsize == 64) + temp |= (svga->dac_pos >> 8) & 0x03; + return temp; + } + return 0xff; + } else /*REG02*/ + return svga_in(addr, svga); + } + break; + + case 0x3C7: + if (rs2) { + if (rs3) /*REG0F, Hardware Cursor Y-position, write only*/ + return 0xff; + else /*REG07, Cursor/Overscan Read Address*/ + return svga->dac_status; + } else { + if (rs3) { /*REG0B, Cursor Ram Data*/ + if (svga->hwcursor.xsize == 64) + cd = (uint8_t *) ramdac->cursor64_data; + else + cd = (uint8_t *) ramdac->cursor32_data; + + temp = cd[svga->dac_pos]; + svga->dac_pos++; + if (svga->hwcursor.xsize == 32) + svga->dac_pos &= 0x00ff; + else + svga->dac_pos &= 0x03ff; + return temp; + } else /*REG03*/ + return svga_in(addr, svga); + } + break; + + case 0x3C8: + if (rs2) { + if (rs3) /*REG0C, Hardware Cursor X-position, write only*/ + return 0xff; + else /*REG04, Cursor/Overscan Write Address*/ + return svga->dac_write; + } else { + if (rs3) /*REG08, Command Reg 1*/ + return ramdac->cr1; + else /*REG00*/ + return svga_in(addr, svga); + } + break; + + case 0x3C9: + if (rs2) { + if (rs3) /*REG0D, Hardware Cursor X-position, write only*/ + return 0xff; + else { /*REG05, Cursor/Overscan Data*/ + svga->dac_status = 0; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + return ramdac->extpal[svga->dac_read].r & 0x3f; + case 1: + svga->dac_pos++; + return ramdac->extpal[svga->dac_read].g & 0x3f; + case 2: + svga->dac_pos=0; + svga->dac_read = (svga->dac_read + 1) & 15; + return ramdac->extpal[(svga->dac_read - 1) & 15].b & 0x3f; + + } + return 0xff; + } + } else { + if (rs3) /*REG09, Command Reg 2*/ + return ramdac->cr2; + else /*REG01*/ + return svga_in(addr, svga); + } + break; + } + + return temp; } diff --git a/src/video/vid_bt485_ramdac.h b/src/video/vid_bt485_ramdac.h index 12d535359..14ec3eae3 100644 --- a/src/video/vid_bt485_ramdac.h +++ b/src/video/vid_bt485_ramdac.h @@ -3,16 +3,18 @@ */ typedef struct bt485_ramdac_t { - int magic_count; - uint8_t command; - int windex, rindex; - uint16_t regs[256]; - int reg_ff; - int rs2; - int rs3; + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + int set_reg0a; + int hwc_y, hwc_x; + uint8_t cr0; + uint8_t cr1; + uint8_t cr2; + uint8_t cr3; } bt485_ramdac_t; -void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga); -uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga); +void bt485_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga); +uint8_t bt485_ramdac_in(uint16_t addr, int rs2, int rs3, bt485_ramdac_t *ramdac, svga_t *svga); -float bt485_getclock(int clock, void *p); diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 2290794f0..7345aa1c0 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.21 2018/09/19 + * Version: @(#)vid_cl_54xx.c 1.0.22 2018/09/30 * * Authors: Sarah Walker, * Barry Rodewald, @@ -308,6 +308,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) svga_recalctimings(svga); svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW; svga->hwcursor.xsize = svga->hwcursor.ysize = (val & CIRRUS_CURSOR_LARGE) ? 64 : 32; + svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; if (val & CIRRUS_CURSOR_LARGE) svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256)); else diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 35ba8ba09..b95887b08 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -10,7 +10,7 @@ * * Known bugs: Accelerator doesn't work in planar modes * - * Version: @(#)vid_et4000w32.c 1.0.17 2018/09/19 + * Version: @(#)vid_et4000w32.c 1.0.18 2018/09/30 * * Authors: Sarah Walker, * Miran Grca, @@ -35,15 +35,11 @@ #include "../plat.h" #include "video.h" #include "vid_svga.h" -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) #include "vid_icd2061.h" -#endif #include "vid_stg_ramdac.h" -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) #define BIOS_ROM_PATH_DIAMOND L"roms/video/et4000w32/et4000w32.bin" -#endif #define BIOS_ROM_PATH_CARDEX L"roms/video/et4000w32/cardex.vbi" @@ -61,9 +57,7 @@ enum { ET4000W32_CARDEX = 0, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) ET4000W32_DIAMOND -#endif }; enum @@ -88,9 +82,7 @@ typedef struct et4000w32p_t svga_t svga; stg_ramdac_t ramdac; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) icd2061_t icd2061; -#endif int index; int pci; @@ -196,12 +188,10 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) switch (addr) { -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) case 0x3c2: if (et4000->type == ET4000W32_DIAMOND) icd2061_write(&et4000->icd2061, (val >> 2) & 3); break; -#endif case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: stg_ramdac_out(addr, val, &et4000->ramdac, svga); @@ -366,22 +356,12 @@ void et4000w32p_recalctimings(svga_t *svga) if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) if (et4000->type == ET4000W32_DIAMOND) { - switch ((svga->miscout >> 2) & 3) - { - case 0: case 1: break; - case 2: case 3: svga->clock = cpuclock / icd2061_getfreq(&et4000->icd2061, 2); break; - } + svga->clock = cpuclock / icd2061_getclock((svga->miscout >> 2) & 3, &et4000->icd2061); } else - { -#endif svga->clock = cpuclock / stg_getclock((svga->miscout >> 2) & 3, &et4000->ramdac); -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - } -#endif switch (svga->bpp) { @@ -1275,12 +1255,12 @@ void *et4000w32p_init(const device_t *info) rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) + case ET4000W32_DIAMOND: rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + icd2061_init(&et4000->icd2061); break; -#endif } et4000->pci = !!(info->flags & DEVICE_PCI); if (info->flags & DEVICE_PCI) @@ -1316,12 +1296,10 @@ void *et4000w32p_init(const device_t *info) return et4000; } -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) int et4000w32p_available(void) { return rom_present(BIOS_ROM_PATH_DIAMOND); } -#endif int et4000w32p_cardex_available(void) { @@ -1398,7 +1376,6 @@ const device_t et4000w32p_cardex_pci_device = et4000w32p_config }; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) const device_t et4000w32p_vlb_device = { "Tseng Labs ET4000/w32p VLB (Diamond)", @@ -1420,4 +1397,3 @@ const device_t et4000w32p_pci_device = et4000w32p_force_redraw, et4000w32p_config }; -#endif diff --git a/src/video/vid_et4000w32.h b/src/video/vid_et4000w32.h index 80a14e5d4..350933be5 100644 --- a/src/video/vid_et4000w32.h +++ b/src/video/vid_et4000w32.h @@ -1,7 +1,5 @@ -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) extern const device_t et4000w32p_vlb_device; extern const device_t et4000w32p_pci_device; -#endif extern const device_t et4000w32p_cardex_vlb_device; extern const device_t et4000w32p_cardex_pci_device; diff --git a/src/video/vid_icd2061.c b/src/video/vid_icd2061.c index e8aaf05cb..dfe5c6a2c 100644 --- a/src/video/vid_icd2061.c +++ b/src/video/vid_icd2061.c @@ -10,71 +10,106 @@ * * Used by ET4000w32/p (Diamond Stealth 32) * - * Version: @(#)vid_icd2061.c 1.0.2 2017/11/04 + * Version: @(#)vid_icd2061.c 1.0.3 2018/09/30 * - * Authors: Sarah Walker, - * Miran Grca, + * Authors: Miran Grca, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. + * Copyright 2016-2018 Miran Grca. */ #include #include #include #include #include "../86box.h" +#include "../mem.h" +#include "video.h" +#include "vid_svga.h" #include "vid_icd2061.h" - -void icd2061_write(icd2061_t *icd2061, int val) +void +icd2061_write(icd2061_t *icd2061, int val) { - int q, p, m, a; - if ((val & 1) && !(icd2061->state & 1)) - { - if (!icd2061->status) - { - if (val & 2) - icd2061->unlock++; - else - { - if (icd2061->unlock >= 5) - { - icd2061->status = 1; - icd2061->pos = 0; - } - else - icd2061->unlock = 0; - } - } - else if (val & 1) - { - icd2061->data = (icd2061->data >> 1) | (((val & 2) ? 1 : 0) << 24); - icd2061->pos++; - if (icd2061->pos == 26) - { - a = (icd2061->data >> 21) & 0x7; - if (!(a & 4)) - { - q = (icd2061->data & 0x7f) - 2; - m = 1 << ((icd2061->data >> 7) & 0x7); - p = ((icd2061->data >> 10) & 0x7f) - 3; - if (icd2061->ctrl & (1 << a)) - p <<= 1; - icd2061->freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m; - } - else if (a == 6) - { - icd2061->ctrl = val; - } - icd2061->unlock = icd2061->data = 0; - icd2061->status = 0; - } - } - } - icd2061->state = val; + int /*od, */nd, oc, nc; + int a/*, i*/, qa, q, pa, p, m; + +#if 0 + od = (icd2061->state & 2) >> 1; /* Old data. */ +#endif + nd = (val & 2) >> 1; /* Old data. */ + oc = icd2061->state & 1; /* Old clock. */ + nc = val & 1; /* New clock. */ + + icd2061->state = val; + + if (nc && !oc) { /* Low-to-high transition of CLK. */ + if (!icd2061->unlocked) { + if (nd) { /* DATA high. */ + icd2061->count++; + /* pclog("Low-to-high transition of CLK with DATA high, %i total\n", icd2061->count); */ + } else { /* DATA low. */ + if (icd2061->count >= 5) { + icd2061->unlocked = 1; + icd2061->bit_count = icd2061->data = 0; + /* pclog("ICD2061 unlocked\n"); */ + } else { + icd2061->count = 0; + /* pclog("ICD2061 locked\n"); */ + } + } + } else if (nc) { + icd2061->data |= (nd << icd2061->bit_count); + icd2061->bit_count++; + + if (icd2061->bit_count == 26) { + icd2061->data >>= 1; + /* pclog("26 bits received, data = %08X\n", icd2061->data); */ + + a = ((icd2061->data >> 21) & 0x07); /* A */ + + if (a < 3) { +#if 0 + i = ((icd2061->data >> 17) & 0x0f); /* I */ +#endif + pa = ((icd2061->data >> 10) & 0x7f); /* P' */ + m = ((icd2061->data >> 7) & 0x07); /* M */ + qa = (icd2061->data & 0x7f); /* Q' */ + + p = pa + 3; /* P */ + m = 1 << m; + q = qa + 2; /* Q */ + + if (icd2061->ctrl & (1 << a)) + p <<= 1; + icd2061->freq[a] = ((float)p / (float)q) * 2.0 * 14318184.0 / (float)m; + + /* pclog("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p, m, q, a, icd2061->freq[a]); */ + } else if (a == 6) { + icd2061->ctrl = val; + /* pclog("ctrl = %02X\n", icd2061->ctrl); */ + } + icd2061->count = icd2061->bit_count = icd2061->data = 0; + } + } + } } -double icd2061_getfreq(icd2061_t *icd2061, int i) + +void +icd2061_init(icd2061_t *icd2061) { - return icd2061->freq[i]; + icd2061->freq[0] = 25175000.0; + icd2061->freq[1] = 28322000.0; + icd2061->freq[2] = 28322000.0; +} + + +float +icd2061_getclock(int clock, void *p) +{ + icd2061_t *icd2061 = (icd2061_t *) p; + + if (clock > 2) + clock = 2; + + return icd2061->freq[clock]; } diff --git a/src/video/vid_icd2061.h b/src/video/vid_icd2061.h index acb6821cf..6a203dc52 100644 --- a/src/video/vid_icd2061.h +++ b/src/video/vid_icd2061.h @@ -1,17 +1,31 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ +/* + * 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. + * + * ICD2061 clock generator emulation header. + * + * Used by ET4000w32/p (Diamond Stealth 32) + * + * Version: @(#)vid_icd2061.h 1.0.0 2018/09/30 + * + * Authors: Miran Grca, + * + * Copyright 2018 Miran Grca. + */ typedef struct icd2061_t { - int state; - int status; - int pos; - int unlock; - uint32_t data; + svga_t svga; + float freq[3]; - double freq[4]; - uint32_t ctrl; + int count, bit_count; + int unlocked, state; + uint32_t data, ctrl; } icd2061_t; void icd2061_write(icd2061_t *icd2061, int val); -double icd2061_getfreq(icd2061_t *icd2061, int i); +void icd2061_init(icd2061_t *icd2061); +float icd2061_getclock(int clock, void *p); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index e24beb0d2..a135eeaed 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -8,7 +8,7 @@ * * S3 emulation. * - * Version: @(#)vid_s3.c 1.0.18 2018/09/22 + * Version: @(#)vid_s3.c 1.0.18 2018/09/30 * * Authors: Sarah Walker, * Miran Grca, @@ -33,48 +33,50 @@ #include "vid_svga.h" #include "vid_svga_render.h" #include "vid_sdac_ramdac.h" +#include "vid_bt485_ramdac.h" +#include "vid_icd2061.h" #define ROM_PARADISE_BAHAMAS64 L"roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 L"roms/video/s3/86c864p.bin" -#define ROM_EXPERTCOLOR_DSV3868P_CF55 L"roms/video/s3/1-DSV3868.BIN" +#define ROM_DIAMOND_STEALTH64_964 L"roms/video/s3/964_107u.rom" #define ROM_PHOENIX_TRIO32 L"roms/video/s3/86c732p.bin" #define ROM_NUMBER9_9FX L"roms/video/s3/s3_764.bin" #define ROM_PHOENIX_TRIO64 L"roms/video/s3/86c764x1.bin" -#define ROM_DIAMOND_STEALTH64 L"roms/video/s3/stealt64.bin" +#define ROM_DIAMOND_STEALTH64_764 L"roms/video/s3/stealt64.bin" enum { - S3_EXPERTCOLOR_DSV3868P_CF55, S3_NUMBER9_9FX, S3_PARADISE_BAHAMAS64, + S3_DIAMOND_STEALTH64_964, S3_PHOENIX_TRIO32, S3_PHOENIX_TRIO64, S3_PHOENIX_TRIO64_ONBOARD, S3_PHOENIX_VISION864, - S3_DIAMOND_STEALTH64 + S3_DIAMOND_STEALTH64_764 }; enum { - S3_VISION864, - S3_VISION868, - S3_TRIO32, - S3_TRIO64 + S3_VISION864, + S3_VISION964, + S3_TRIO32, + S3_TRIO64 }; static video_timings_t timing_s3_stealth64 = {VIDEO_BUS, 2, 2, 4, 26, 26, 42}; static video_timings_t timing_s3_vision864 = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; -static video_timings_t timing_s3_vision868 = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision964 = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_trio32 = {VIDEO_BUS, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio64 = {VIDEO_BUS, 3, 2, 4, 25, 25, 40}; enum { - VRAM_4MB = 0, - VRAM_8MB = 3, - VRAM_2MB = 4, - VRAM_1MB = 6, - VRAM_512KB = 7 + VRAM_4MB = 0, + VRAM_8MB = 3, + VRAM_2MB = 4, + VRAM_1MB = 6, + VRAM_512KB = 7 }; #define FIFO_SIZE 65536 @@ -90,113 +92,117 @@ enum enum { - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24), - FIFO_OUT_BYTE = (0x04 << 24), - FIFO_OUT_WORD = (0x05 << 24), - FIFO_OUT_DWORD = (0x06 << 24) + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24), + FIFO_OUT_BYTE = (0x04 << 24), + FIFO_OUT_WORD = (0x05 << 24), + FIFO_OUT_DWORD = (0x06 << 24) }; typedef struct { - uint32_t addr_type; - uint32_t val; + uint32_t addr_type; + uint32_t val; } fifo_entry_t; typedef struct s3_t { - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; + mem_mapping_t linear_mapping; + mem_mapping_t mmio_mapping; mem_mapping_t new_mmio_mapping; - + uint8_t has_bios; - rom_t bios_rom; + rom_t bios_rom; - svga_t svga; - sdac_ramdac_t ramdac; + svga_t svga; + sdac_ramdac_t ramdac; + bt485_ramdac_t bt485_ramdac; + icd2061_t icd2061; - uint8_t bank; - uint8_t ma_ext; - int width; - int bpp; + uint8_t bank; + uint8_t ma_ext; + int width; + int bpp; - int chip, pci; - - uint8_t id, id_ext, id_ext_pci; - - uint8_t int_line; - - int packed_mmio; + int chip, pci; + + uint8_t id, id_ext, id_ext_pci; + + uint8_t int_line; + + int packed_mmio; + + int p86c911_compat; - uint32_t linear_base, linear_size; - - uint8_t pci_regs[256]; - int card; + uint32_t linear_base, linear_size; + + uint8_t pci_regs[256]; + int card; - uint32_t vram_mask; - uint8_t status_9ae8; - - float (*getclock)(int clock, void *p); - void *getclock_p; + uint32_t vram_mask; + uint8_t status_9ae8; + + float (*getclock)(int clock, void *p); + void *getclock_p; - struct - { - uint16_t subsys_cntl; - uint16_t setup_md; - uint8_t advfunc_cntl; - uint16_t cur_y, cur_y2; - uint16_t cur_x, cur_x2; - uint16_t x2; - int16_t desty_axstp, desty_axstp2; - int16_t destx_distp; - int16_t err_term, err_term2; - int16_t maj_axis_pcnt, maj_axis_pcnt2; - uint16_t cmd; - uint16_t short_stroke; - uint32_t bkgd_color; - uint32_t frgd_color; - uint32_t wrt_mask; - uint32_t rd_mask; - uint32_t color_cmp; - uint8_t bkgd_mix; - uint8_t frgd_mix; - uint16_t multifunc_cntl; - uint16_t multifunc[16]; - uint8_t pix_trans[4]; - - int cx, cy; - int sx, sy; - int dx, dy; - uint32_t src, dest, pattern; - int pix_trans_count; + struct + { + uint16_t subsys_cntl; + uint16_t setup_md; + uint8_t advfunc_cntl; + uint16_t cur_y, cur_y2; + uint16_t cur_x, cur_x2; + uint16_t x2; + int16_t desty_axstp, desty_axstp2; + int16_t destx_distp; + int16_t err_term, err_term2; + int16_t maj_axis_pcnt, maj_axis_pcnt2; + uint16_t cmd; + uint16_t short_stroke; + uint32_t bkgd_color; + uint32_t frgd_color; + uint32_t wrt_mask; + uint32_t rd_mask; + uint32_t color_cmp; + uint8_t bkgd_mix; + uint8_t frgd_mix; + uint16_t multifunc_cntl; + uint16_t multifunc[16]; + uint8_t pix_trans[4]; + + int cx, cy; + int sx, sy; + int dx, dy; + uint32_t src, dest, pattern; + int pix_trans_count; - int poly_cx, poly_cx2; - int poly_cy, poly_cy2; - int point_1_updated, point_2_updated; - int poly_dx1, poly_dx2; - int poly_x; + int poly_cx, poly_cx2; + int poly_cy, poly_cy2; + int point_1_updated, point_2_updated; + int poly_dx1, poly_dx2; + int poly_x; - uint32_t dat_buf; - int dat_count; - } accel; + uint32_t dat_buf; + int dat_count; + } accel; - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - - uint8_t subsys_cntl, subsys_stat; - - uint32_t hwc_fg_col, hwc_bg_col; - int hwc_col_stack_pos; + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; + + uint8_t subsys_cntl, subsys_stat; + + uint32_t hwc_fg_col, hwc_bg_col; + int hwc_col_stack_pos; } s3_t; #define INT_VSY (1 << 0) @@ -214,16 +220,16 @@ uint8_t s3_accel_read(uint32_t addr, void *p); static inline void wake_fifo_thread(s3_t *s3) { - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ } static void s3_wait_fifo_idle(s3_t *s3) { - while (!FIFO_EMPTY) - { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } + while (!FIFO_EMPTY) + { + wake_fifo_thread(s3); + thread_wait_event(s3->fifo_not_full_event, 1); + } } static void s3_update_irqs(s3_t *s3) @@ -233,1123 +239,1175 @@ static void s3_update_irqs(s3_t *s3) return; } - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) - pci_set_irq(s3->card, PCI_INTA); - else - pci_clear_irq(s3->card, PCI_INTA); + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + pci_set_irq(s3->card, PCI_INTA); + else + pci_clear_irq(s3->card, PCI_INTA); } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); -#define WRITE8(addr, var, val) switch ((addr) & 3) \ - { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } +#define WRITE8(addr, var, val) switch ((addr) & 3) \ + { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ + } static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { - switch (port) - { - case 0x82e8: - s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; - s3->accel.poly_cy = s3->accel.cur_y; - break; - case 0x82e9: - s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8); - s3->accel.poly_cy = s3->accel.cur_y; - break; - case 0x82ea: - s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; - s3->accel.poly_cy2 = s3->accel.cur_y2; - break; - case 0x82eb: - s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8); - s3->accel.poly_cy2 = s3->accel.cur_y2; - break; - - case 0x86e8: - s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; - s3->accel.poly_cx = s3->accel.cur_x << 20; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - break; - case 0x86e9: - s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8); - s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - break; - case 0x86ea: - s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; - s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; - break; - case 0x86eb: - s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8); - s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; - break; - - case 0x8ae8: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; - s3->accel.point_1_updated = 1; - break; - case 0x8ae9: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.desty_axstp |= ~0x3fff; - s3->accel.point_1_updated = 1; - break; - case 0x8aea: - s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; - s3->accel.point_2_updated = 1; - break; - case 0x8aeb: - s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.desty_axstp2 |= ~0x3fff; - s3->accel.point_2_updated = 1; - break; - - case 0x8ee8: - s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; - s3->accel.point_1_updated = 1; - break; - case 0x8ee9: - s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.destx_distp |= ~0x3fff; - s3->accel.point_1_updated = 1; - break; - case 0x8eea: - s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; - s3->accel.point_2_updated = 1; - break; - case 0x8eeb: - s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8); - s3->accel.point_2_updated = 1; - break; - - case 0x92e8: - s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; - break; - case 0x92e9: - s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.err_term |= ~0x3fff; - break; - case 0x92ea: - s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; - break; - case 0x92eb: - s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.err_term2 |= ~0x3fff; - break; + switch (port) + { + case 0x82e8: + s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x82e9: + s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x82ea: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + case 0x82eb: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + + case 0x86e8: + s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; + s3->accel.poly_cx = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x86e9: + s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x86ea: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + case 0x86eb: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + + case 0x8ae8: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0x8ae9: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8aea: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8aeb: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp2 |= ~0x3fff; + s3->accel.point_2_updated = 1; + break; + + case 0x8ee8: + s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0x8ee9: + s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.destx_distp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8eea: + s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8eeb: + s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8); + s3->accel.point_2_updated = 1; + break; + + case 0x92e8: + s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; + break; + case 0x92e9: + s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term |= ~0x3fff; + break; + case 0x92ea: + s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; + break; + case 0x92eb: + s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term2 |= ~0x3fff; + break; - case 0x96e8: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val; - break; - case 0x96e9: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt |= ~0x0fff; - break; - case 0x96ea: - s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; - break; - case 0x96eb: - s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt2 |= ~0x0fff; - break; + case 0x96e8: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val; + break; + case 0x96e9: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); + if (val & 0x08) + s3->accel.maj_axis_pcnt |= ~0x0fff; + break; + case 0x96ea: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; + break; + case 0x96eb: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); + if (val & 0x08) + s3->accel.maj_axis_pcnt2 |= ~0x0fff; + break; - case 0x9ae8: - s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; - break; - case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.pix_trans_count = 0; - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ - break; + case 0x9ae8: + s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; + break; + case 0x9ae9: + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3_accel_start(-1, 0, 0xffffffff, 0, s3); + s3->accel.pix_trans_count = 0; + s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ + break; - case 0x9ee8: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; - break; - case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); - break; + case 0x9ee8: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; + break; + case 0x9ee9: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + break; - case 0xa2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; - break; - case 0xa2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; - } - break; - case 0xa2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xa2e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + break; + case 0xa2e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa2ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } + break; + case 0xa2eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xa6e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; - break; - case 0xa6e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; - } - break; - case 0xa6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xa6e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + break; + case 0xa6e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa6ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } + break; + case 0xa6eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xaae8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; - break; - case 0xaae9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xaaea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; - } - break; - case 0xaaeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xaae8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + break; + case 0xaae9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xaaea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } + break; + case 0xaaeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xaee8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; - break; - case 0xaee9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xaeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; - } - break; - case 0xaeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xaee8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + break; + case 0xaee9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xaeea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } + break; + case 0xaeeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xb2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; - break; - case 0xb2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xb2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; - } - break; - case 0xb2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) - { - if (s3->accel.multifunc[0xe] & 0x10) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; - } - break; + case 0xb2e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + break; + case 0xb2e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xb2ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } + break; + case 0xb2eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xb6e8: - s3->accel.bkgd_mix = val; - break; + case 0xb6e8: + s3->accel.bkgd_mix = val; + break; - case 0xbae8: - s3->accel.frgd_mix = val; - break; - - case 0xbee8: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; - break; - case 0xbee9: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); - s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; - break; + case 0xbae8: + s3->accel.frgd_mix = val; + break; + + case 0xbee8: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; + break; + case 0xbee9: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); + s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + break; - case 0xe2e8: - s3->accel.pix_trans[0] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - break; - case 0xe2e9: - s3->accel.pix_trans[1] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0xe2ea: - s3->accel.pix_trans[2] = val; - break; - case 0xe2eb: - s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32) - { - s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - } - else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100)) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - } + case 0xe2e8: + s3->accel.pix_trans[0] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + break; + case 0xe2e9: + s3->accel.pix_trans[1] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + { + if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0xe2ea: + s3->accel.pix_trans[2] = val; + break; + case 0xe2eb: + s3->accel.pix_trans[3] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) - { - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(8, 1, val | (val << 16), 0, s3); - else - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - else - { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } - } + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(8, 1, val | (val << 16), 0, s3); + else + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } + else + { + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + } } static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - else if (s3->accel.cmd & 0x400) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } - else - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } - else - { - if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val, s3); - else if ((s3->accel.cmd & 0x600) == 0x200) - { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - else - { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - } - } + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } + else + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } + } + else + { + if (s3->accel.cmd & 0x400) + s3_accel_start(4, 1, 0xffffffff, val, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) + { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + else + { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + } + } } static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { - if (s3->packed_mmio) - { - int addr_lo = addr & 1; - switch (addr & 0xfffe) - { - case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ - case 0x8102: addr = 0x86e8; break; - - case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ - case 0x8106: addr = 0x86ea; break; - - case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ - case 0x810a: addr = 0x8ee8; break; - - case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ - case 0x810e: addr = 0x8eea; break; + if (s3->packed_mmio) + { + int addr_lo = addr & 1; + switch (addr & 0xfffe) + { + case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ + case 0x8102: addr = 0x86e8; break; + + case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ + case 0x8106: addr = 0x86ea; break; + + case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ + case 0x810a: addr = 0x8ee8; break; + + case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ + case 0x810e: addr = 0x8eea; break; - case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ - case 0x8112: addr = 0x92ee; break; + case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ + case 0x8112: addr = 0x92ee; break; - case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ - case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ - - case 0x8120: case 0x8122: /*BKGD_COLOR*/ - WRITE8(addr, s3->accel.bkgd_color, val); - return; - - case 0x8124: case 0x8126: /*FRGD_COLOR*/ - WRITE8(addr, s3->accel.frgd_color, val); - return; + case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ + case 0x811a: addr = 0x9aea; break; + + case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ + + case 0x8120: case 0x8122: /*BKGD_COLOR*/ + WRITE8(addr, s3->accel.bkgd_color, val); + return; + + case 0x8124: case 0x8126: /*FRGD_COLOR*/ + WRITE8(addr, s3->accel.frgd_color, val); + return; - case 0x8128: case 0x812a: /*WRT_MASK*/ - WRITE8(addr, s3->accel.wrt_mask, val); - return; + case 0x8128: case 0x812a: /*WRT_MASK*/ + WRITE8(addr, s3->accel.wrt_mask, val); + return; - case 0x812c: case 0x812e: /*RD_MASK*/ - WRITE8(addr, s3->accel.rd_mask, val); - return; + case 0x812c: case 0x812e: /*RD_MASK*/ + WRITE8(addr, s3->accel.rd_mask, val); + return; - case 0x8130: case 0x8132: /*COLOR_CMP*/ - WRITE8(addr, s3->accel.color_cmp, val); - return; + case 0x8130: case 0x8132: /*COLOR_CMP*/ + WRITE8(addr, s3->accel.color_cmp, val); + return; - case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ - case 0x8136: addr = 0xbae8; break; - - case 0x8138: /*SCISSORS_T*/ - WRITE8(addr & 1, s3->accel.multifunc[1], val); - return; - case 0x813a: /*SCISSORS_L*/ - WRITE8(addr & 1, s3->accel.multifunc[2], val); - return; - case 0x813c: /*SCISSORS_B*/ - WRITE8(addr & 1, s3->accel.multifunc[3], val); - return; - case 0x813e: /*SCISSORS_R*/ - WRITE8(addr & 1, s3->accel.multifunc[4], val); - return; + case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ + case 0x8136: addr = 0xbae8; break; + + case 0x8138: /*SCISSORS_T*/ + WRITE8(addr & 1, s3->accel.multifunc[1], val); + return; + case 0x813a: /*SCISSORS_L*/ + WRITE8(addr & 1, s3->accel.multifunc[2], val); + return; + case 0x813c: /*SCISSORS_B*/ + WRITE8(addr & 1, s3->accel.multifunc[3], val); + return; + case 0x813e: /*SCISSORS_R*/ + WRITE8(addr & 1, s3->accel.multifunc[4], val); + return; - case 0x8140: /*PIX_CNTL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xa], val); - return; - case 0x8142: /*MULT_MISC2*/ - WRITE8(addr & 1, s3->accel.multifunc[0xd], val); - return; - case 0x8144: /*MULT_MISC*/ - WRITE8(addr & 1, s3->accel.multifunc[0xe], val); - return; - case 0x8146: /*READ_SEL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xf], val); - return; + case 0x8140: /*PIX_CNTL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xa], val); + return; + case 0x8142: /*MULT_MISC2*/ + WRITE8(addr & 1, s3->accel.multifunc[0xd], val); + return; + case 0x8144: /*MULT_MISC*/ + WRITE8(addr & 1, s3->accel.multifunc[0xe], val); + return; + case 0x8146: /*READ_SEL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xf], val); + return; - case 0x8148: /*ALT_PCNT*/ - WRITE8(addr & 1, s3->accel.multifunc[0], val); - return; - case 0x814a: addr = 0x96e8; break; - case 0x814c: addr = 0x96ea; break; + case 0x8148: /*ALT_PCNT*/ + WRITE8(addr & 1, s3->accel.multifunc[0], val); + return; + case 0x814a: addr = 0x96e8; break; + case 0x814c: addr = 0x96ea; break; - case 0x8168: addr = 0xeae8; break; - case 0x816a: addr = 0xeaea; break; - } - addr |= addr_lo; - } - + case 0x8168: addr = 0xeae8; break; + case 0x816a: addr = 0xeaea; break; + } + addr |= addr_lo; + } + - if (addr & 0x8000) - { - s3_accel_out_fifo(s3, addr & 0xffff, val); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } - } + if (addr & 0x8000) + { + s3_accel_out_fifo(s3, addr & 0xffff, val); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } } static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { - if (addr & 0x8000) - { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) - { - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(8, 1, val | (val << 16), 0, s3); - else - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - else - { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } - } - } + if (addr & 0x8000) + { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(8, 1, val | (val << 16), 0, s3); + else + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } + else + { + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + } + } } static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { - if (addr & 0x8000) - { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); - } - else if (s3->accel.cmd & 0x400) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } - else - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } - else - { - if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val, s3); - else if ((s3->accel.cmd & 0x600) == 0x200) - { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - else - { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - } - } - } + if (addr & 0x8000) + { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } + else + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } + } + else + { + if (s3->accel.cmd & 0x400) + s3_accel_start(4, 1, 0xffffffff, val, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) + { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + else + { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + } + } + } } static void fifo_thread(void *param) { - s3_t *s3 = (s3_t *)param; - - while (1) - { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; + s3_t *s3 = (s3_t *)param; + + while (1) + { + thread_set_event(s3->fifo_not_full_event); + thread_wait_event(s3->wake_fifo_thread, -1); + thread_reset_event(s3->wake_fifo_thread); + s3->blitter_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_BYTE: + s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_WORD: + s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_DWORD: + s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_BYTE: + s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_WORD: + s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_DWORD: + s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + } + + s3->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); + if (FIFO_ENTRIES > 0xe000) + thread_set_event(s3->fifo_not_full_event); - end_time = plat_timer_read(); - s3->blitter_time += end_time - start_time; - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } + end_time = plat_timer_read(); + s3->blitter_time += end_time - start_time; + } + s3->blitter_busy = 0; + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); + } } static void s3_vblank_start(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; + s3_t *s3 = (s3_t *)svga->p; - s3->subsys_stat |= INT_VSY; - s3_update_irqs(s3); + s3->subsys_stat |= INT_VSY; + s3_update_irqs(s3); } static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - if (FIFO_FULL) - { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } + if (FIFO_FULL) + { + thread_reset_event(s3->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); + s3->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(s3); } void s3_out(uint16_t addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint8_t old; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) - { - case 0x12: case 0x13: - svga_recalctimings(svga); - return; - } - } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { - if (val & 8) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + switch (addr) + { + case 0x3c2: + if (s3->chip == S3_VISION964) { + if (((val >> 2) & 3) != 3) + icd2061_write(&s3->icd2061, (val >> 2) & 3); + } break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - svga_out(addr, val, svga); - else - { - if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) - sdac_ramdac_out(addr, 1, val, &s3->ramdac, svga); - else - sdac_ramdac_out(addr, 0, val, &s3->ramdac, svga); - } - return; - case 0x3D4: - svga->crtcreg = val & 0x7f; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - switch (svga->crtcreg) - { - case 0x31: - s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); - break; - case 0x32: - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; - break; - - case 0x50: - switch (svga->crtc[0x50] & 0xc1) - { - case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; - case 0x01: s3->width = 1152; break; - case 0x40: s3->width = 640; break; - case 0x80: s3->width = 800; break; - case 0x81: s3->width = 1600; break; - case 0xc0: s3->width = 1280; break; - } - s3->bpp = (svga->crtc[0x50] >> 4) & 3; - break; - case 0x69: - s3->ma_ext = val & 0x1f; - break; - - case 0x35: - s3->bank = (s3->bank & 0x70) | (val & 0xf); - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - case 0x51: - s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); - break; - case 0x6a: - s3->bank = val; - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - - case 0x45: - svga->hwcursor.ena = val & 1; - break; - case 0x48: - svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - if (svga->bpp == 32) svga->hwcursor.x >>= 1; - svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - 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) - svga->hwcursor.x <<= 1; - break; + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) + { + case 0x12: case 0x13: + svga_recalctimings(svga); + return; + } + } + if (svga->seqaddr == 4) /*Chain-4 - update banking*/ + { + if (val & 8) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + } + break; + + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + svga_out(addr, val, svga); + else if (s3->chip == S3_VISION964) + { + if (svga->crtc[0x55] == 3) + bt485_ramdac_out(addr, 1, 1, val, &s3->bt485_ramdac, svga); + else if (svga->crtc[0x55] == 2) + bt485_ramdac_out(addr, 0, 1, val, &s3->bt485_ramdac, svga); + else if ((svga->crtc[0x55] == 1) || (svga->crtc[0x43] & 2)) + bt485_ramdac_out(addr, 1, 0, val, &s3->bt485_ramdac, svga); + else + bt485_ramdac_out(addr, 0, 0, val, &s3->bt485_ramdac, svga); + } + else + { + if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) + sdac_ramdac_out(addr, 1, val, &s3->ramdac, svga); + else + sdac_ramdac_out(addr, 0, val, &s3->ramdac, svga); + } + return; - case 0x4a: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; - break; - case 0x4b: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; - break; + case 0x3D4: + svga->crtcreg = val & 0x7f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) + { + case 0x31: + s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + break; + case 0x32: + svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + break; - case 0x53: - case 0x58: case 0x59: case 0x5a: - s3_updatemapping(s3); - break; - - case 0x67: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64 || s3->chip == S3_VISION868) - { - switch (val >> 4) - { - case 3: svga->bpp = 15; break; - case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = 32; break; - default: svga->bpp = 8; break; - } - } - break; - } - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - svga_out(addr, val, svga); + case 0x50: + switch (svga->crtc[0x50] & 0xc1) + { + case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; + case 0x01: s3->width = 1152; break; + case 0x40: s3->width = 640; break; + case 0x80: s3->width = 800; break; + case 0x81: s3->width = 1600; break; + case 0xc0: s3->width = 1280; break; + } + s3->bpp = (svga->crtc[0x50] >> 4) & 3; + break; + case 0x69: + s3->ma_ext = val & 0x1f; + break; + + case 0x35: + s3->bank = (s3->bank & 0x70) | (val & 0xf); + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + case 0x51: + s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + break; + case 0x6a: + s3->bank = val; + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + + case 0x3a: + if (val & 0x10) + svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ + break; + + case 0x45: + if (s3->chip == S3_VISION964) + break; + svga->hwcursor.ena = val & 1; + break; + case 0x48: + if (s3->chip == S3_VISION964) + break; + svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; + /* pclog("X=%d\n", svga->hwcursor.x); */ + if (svga->bpp == 32) svga->hwcursor.x >>= 1; + svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; + /* pclog("Y=%d\n", svga->hwcursor.y); */ + 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) + svga->hwcursor.x <<= 1; + break; + + case 0x4a: + switch (s3->hwc_col_stack_pos) + { + case 0: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; + break; + case 0x4b: + switch (s3->hwc_col_stack_pos) + { + case 0: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; + break; + + case 0x53: + case 0x58: case 0x59: case 0x5a: + s3_updatemapping(s3); + break; + + case 0x42: + if (s3->chip == S3_VISION964) { + if (((svga->miscout >> 2) & 3) == 3) + icd2061_write(&s3->icd2061, svga->crtc[0x42] & 0x0f); + } + break; + + case 0x67: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + { + switch (val >> 4) + { + case 3: svga->bpp = 15; break; + case 5: svga->bpp = 16; break; + case 7: svga->bpp = 24; break; + case 13: svga->bpp = 32; break; + default: svga->bpp = 8; break; + } + } + break; + } + if (old != val) + { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + svga_out(addr, val, svga); } uint8_t s3_in(uint16_t addr, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c1: - if (svga->attraddr > 0x14) - return 0xff; - break; - - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - return svga_in(addr, svga); - if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) - return sdac_ramdac_in(addr, 1, &s3->ramdac, svga); - return sdac_ramdac_in(addr, 0, &s3->ramdac, svga); + switch (addr) + { + case 0x3c1: + if (svga->attraddr > 0x14) + return 0xff; + break; - case 0x3d4: - return svga->crtcreg; - case 0x3d5: - switch (svga->crtcreg) - { - case 0x2d: return 0x88; /*Extended chip ID*/ - case 0x2e: return s3->id_ext; /*New chip ID*/ - case 0x2f: return 0; /*Revision level*/ - case 0x30: - if (s3->chip == S3_VISION868) - return 0xe1; /*Vision868 hardwires it to E1h*/ - else - return s3->id; /*Chip ID*/ - case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); - case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); - case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); - case 0x69: return s3->ma_ext; - case 0x6a: return s3->bank; - } - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + return svga->seqregs[svga->seqaddr]; + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + return svga_in(addr, svga); + if (s3->chip == S3_VISION964) + { + if (svga->crtc[0x55] == 3) + return bt485_ramdac_in(addr, 1, 1, &s3->bt485_ramdac, svga); + else if (svga->crtc[0x55] == 2) + return bt485_ramdac_in(addr, 0, 1, &s3->bt485_ramdac, svga); + else if ((svga->crtc[0x55] == 1) || (svga->crtc[0x43] & 2)) + return bt485_ramdac_in(addr, 1, 0, &s3->bt485_ramdac, svga); + return bt485_ramdac_in(addr, 0, 0, &s3->bt485_ramdac, svga); + } + else + { + if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) + return sdac_ramdac_in(addr, 1, &s3->ramdac, svga); + return sdac_ramdac_in(addr, 0, &s3->ramdac, svga); + } + break; + + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + switch (svga->crtcreg) + { + case 0x2d: return 0x88; /*Extended chip ID*/ + case 0x2e: return s3->id_ext; /*New chip ID*/ + case 0x2f: return 0; /*Revision level*/ + case 0x30: return s3->id; /*Chip ID*/ + case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); + case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); + case 0x45: s3->hwc_col_stack_pos = 0; break; + case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x69: return s3->ma_ext; + case 0x6a: return s3->bank; + } + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); } void s3_recalctimings(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; - svga->hdisp = svga->hdisp_old; + s3_t *s3 = (s3_t *)svga->p; + svga->hdisp = svga->hdisp_old; - svga->ma_latch |= (s3->ma_ext << 16); - if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; - if (svga->crtc[0x5d] & 0x02) - { - svga->hdisp_time += 0x100; - svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); - } - if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; - if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; - if (!svga->rowoffset) svga->rowoffset = 256; - svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + svga->ma_latch |= (s3->ma_ext << 16); + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; + if (svga->crtc[0x5d] & 0x02) + { + svga->hdisp_time += 0x100; + svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + } + if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; + if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; + if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; + if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; + if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; + if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; + if (!svga->rowoffset) svga->rowoffset = 256; - switch (svga->crtc[0x67] >> 4) - { - case 3: case 5: case 7: - svga->clock /= 2; - break; - } + if (s3->chip == S3_VISION964) { + svga->interlace = s3->bt485_ramdac.cr2 & 0x08; + if (s3->bt485_ramdac.cr3 & 0x08) + svga->hdisp *= 2; /* x2 clock multiplier */ + if (((svga->miscout >> 2) & 3) == 3) + svga->clock = cpuclock / s3->getclock(svga->crtc[0x42] & 0x0f, s3->getclock_p); + else + svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + } else { + svga->interlace = svga->crtc[0x42] & 0x20; + svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + } + + switch (svga->crtc[0x67] >> 4) + { + case 3: case 5: case 7: + svga->clock /= 2; + break; + } - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) - { - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - svga->hdisp /= 2; - break; - case 16: - svga->render = svga_render_16bpp_highres; - svga->hdisp /= 2; - break; - case 24: - svga->render = svga_render_24bpp_highres; - svga->hdisp /= 3; - break; - case 32: - svga->render = svga_render_32bpp_highres; - if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64 && s3->chip != S3_VISION868) - svga->hdisp /= 4; - if (s3->chip == S3_VISION868) - svga->hdisp /= 2; - break; - } - } + svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) + { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if (s3->chip != S3_VISION964) + svga->hdisp /= 2; + break; + case 16: + svga->render = svga_render_16bpp_highres; + if (s3->chip != S3_VISION964) + svga->hdisp /= 2; + break; + case 24: + svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; + break; + case 32: + svga->render = svga_render_32bpp_highres; + if ((s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) + svga->hdisp /= 4; + break; + } + } } void s3_updatemapping(s3_t *s3) { - svga_t *svga = &s3->svga; - - if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&s3->linear_mapping); - mem_mapping_disable(&s3->mmio_mapping); + svga_t *svga = &s3->svga; + + if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&s3->linear_mapping); + mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - return; - } + return; + } /*Banked framebuffer*/ - if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ - { + if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ + { /* Enhanced mode forces 64kb at 0xa0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } - else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - - if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ - { - mem_mapping_disable(&svga->mapping); - - s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - switch (svga->crtc[0x58] & 3) - { - case 0: /*64k*/ - s3->linear_size = 0x10000; - break; - case 1: /*1mb*/ - s3->linear_size = 0x100000; - break; - case 2: /*2mb*/ - s3->linear_size = 0x200000; - break; - case 3: /*8mb*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } + else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + + if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ + { + mem_mapping_disable(&svga->mapping); + + s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + switch (svga->crtc[0x58] & 3) + { + case 0: /*64k*/ + s3->linear_size = 0x10000; + break; + case 1: /*1mb*/ + s3->linear_size = 0x100000; + break; + case 2: /*2mb*/ + s3->linear_size = 0x200000; + break; + case 3: /*8mb*/ switch (s3->chip) { case S3_TRIO32: case S3_TRIO64: @@ -1359,468 +1417,460 @@ void s3_updatemapping(s3_t *s3) s3->linear_size = 0x800000; break; } - break; - } - s3->linear_base &= ~(s3->linear_size - 1); - if (s3->linear_base == 0xa0000) - { - mem_mapping_disable(&s3->linear_mapping); - if (!(svga->crtc[0x53] & 0x10)) - { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } - } - else - mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); - } - else - mem_mapping_disable(&s3->linear_mapping); + break; + } + s3->linear_base &= ~(s3->linear_size - 1); + if (s3->linear_base == 0xa0000) + { + mem_mapping_disable(&s3->linear_mapping); + if (!(svga->crtc[0x53] & 0x10)) + { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } + } + else + mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + } + else + mem_mapping_disable(&s3->linear_mapping); /* Memory mapped I/O. */ if (svga->crtc[0x53] & 0x10) { /* Old MMIO. */ mem_mapping_disable(&svga->mapping); mem_mapping_enable(&s3->mmio_mapping); - - /* New MMIO. */ - if ((svga->crtc[0x53] & 0x08) && (s3->chip == S3_VISION868)) - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - else - mem_mapping_disable(&s3->new_mmio_mapping); - } else { + } else mem_mapping_disable(&s3->mmio_mapping); - mem_mapping_disable(&s3->new_mmio_mapping); - } } static float s3_trio64_getclock(int clock, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - float t; - int m, n1, n2; - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - m = svga->seqregs[0x13] + 2; - n1 = (svga->seqregs[0x12] & 0x1f) + 2; - n2 = ((svga->seqregs[0x12] >> 5) & 0x07); - t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); - return t; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + float t; + int m, n1, n2; + if (clock == 0) return 25175000.0; + if (clock == 1) return 28322000.0; + m = svga->seqregs[0x13] + 2; + n1 = (svga->seqregs[0x12] & 0x1f) + 2; + n2 = ((svga->seqregs[0x12] >> 5) & 0x07); + t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); + return t; } void s3_accel_out(uint16_t port, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - - if (port >= 0x8000) - { - s3_queue(s3, port, val, FIFO_OUT_BYTE); - } - else switch (port) - { - case 0x42e8: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x42e9: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x46e8: - s3->accel.setup_md = val; - break; - case 0x4ae8: - s3->accel.advfunc_cntl = val; - break; - } + s3_t *s3 = (s3_t *)p; + + if (port >= 0x8000) + { + s3_queue(s3, port, val, FIFO_OUT_BYTE); + } + else switch (port) + { + case 0x42e8: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x42e9: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x46e8: + s3->accel.setup_md = val; + break; + case 0x4ae8: + s3->accel.advfunc_cntl = val; + break; + } } void s3_accel_out_w(uint16_t port, uint16_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, port, val, FIFO_OUT_WORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, port, val, FIFO_OUT_WORD); } void s3_accel_out_l(uint16_t port, uint32_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, port, val, FIFO_OUT_DWORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, port, val, FIFO_OUT_DWORD); } uint8_t s3_accel_in(uint16_t port, void *p) { - s3_t *s3 = (s3_t *)p; - int temp; - switch (port) - { - case 0x42e8: - return s3->subsys_stat; - case 0x42e9: - return s3->subsys_cntl; + s3_t *s3 = (s3_t *)p; + int temp; + switch (port) + { + case 0x42e8: + return s3->subsys_stat; + case 0x42e9: + return s3->subsys_cntl; - case 0x82e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y & 0xff; - case 0x82e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + case 0x82e8: + s3_wait_fifo_idle(s3); + return s3->accel.cur_y & 0xff; + case 0x82e9: + s3_wait_fifo_idle(s3); + return s3->accel.cur_y >> 8; - case 0x86e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x & 0xff; - case 0x86e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + case 0x86e8: + s3_wait_fifo_idle(s3); + return s3->accel.cur_x & 0xff; + case 0x86e9: + s3_wait_fifo_idle(s3); + return s3->accel.cur_x >> 8; - case 0x8ae8: - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp & 0xff; - case 0x8ae9: - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp >> 8; + case 0x8ae8: + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp & 0xff; + case 0x8ae9: + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp >> 8; - case 0x8ee8: - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp & 0xff; - case 0x8ee9: - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp >> 8; + case 0x8ee8: + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp & 0xff; + case 0x8ee9: + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp >> 8; - case 0x92e8: - s3_wait_fifo_idle(s3); - return s3->accel.err_term & 0xff; - case 0x92e9: - s3_wait_fifo_idle(s3); - return s3->accel.err_term >> 8; + case 0x92e8: + s3_wait_fifo_idle(s3); + return s3->accel.err_term & 0xff; + case 0x92e9: + s3_wait_fifo_idle(s3); + return s3->accel.err_term >> 8; - case 0x96e8: - s3_wait_fifo_idle(s3); - return s3->accel.maj_axis_pcnt & 0xff; - case 0x96e9: - s3_wait_fifo_idle(s3); - return s3->accel.maj_axis_pcnt >> 8; + case 0x96e8: + s3_wait_fifo_idle(s3); + return s3->accel.maj_axis_pcnt & 0xff; + case 0x96e9: + s3_wait_fifo_idle(s3); + return s3->accel.maj_axis_pcnt >> 8; - case 0x9ae8: - if (!s3->blitter_busy) - wake_fifo_thread(s3); - if (FIFO_FULL) - return 0xff; /*FIFO full*/ - return 0; /*FIFO empty*/ - case 0x9ae9: - if (!s3->blitter_busy) - wake_fifo_thread(s3); - temp = 0; - if (!FIFO_EMPTY) - temp |= 0x02; /*Hardware busy*/ - else - temp |= s3->status_9ae8; /*FIFO empty*/ - if (FIFO_FULL) - temp |= 0xf8; /*FIFO full*/ - return temp; + case 0x9ae8: + if (!s3->blitter_busy) + wake_fifo_thread(s3); + if (FIFO_FULL) + return 0xff; /*FIFO full*/ + return 0; /*FIFO empty*/ + case 0x9ae9: + if (!s3->blitter_busy) + wake_fifo_thread(s3); + temp = 0; + if (!FIFO_EMPTY) + temp |= 0x02; /*Hardware busy*/ + else + temp |= s3->status_9ae8; /*FIFO empty*/ + if (FIFO_FULL) + temp |= 0xf8; /*FIFO full*/ + return temp; - case 0xa2e8: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color & 0xff; - case 0xa2e9: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 8; - case 0xa2ea: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 16; - case 0xa2eb: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 24; + case 0xa2e8: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color & 0xff; + case 0xa2e9: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 8; + case 0xa2ea: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 16; + case 0xa2eb: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 24; - case 0xa6e8: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color & 0xff; - case 0xa6e9: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 8; - case 0xa6ea: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 16; - case 0xa6eb: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 24; + case 0xa6e8: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color & 0xff; + case 0xa6e9: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 8; + case 0xa6ea: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 16; + case 0xa6eb: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 24; - case 0xaae8: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask & 0xff; - case 0xaae9: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 8; - case 0xaaea: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 16; - case 0xaaeb: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 24; + case 0xaae8: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask & 0xff; + case 0xaae9: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 8; + case 0xaaea: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 16; + case 0xaaeb: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 24; - case 0xaee8: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask & 0xff; - case 0xaee9: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 8; - case 0xaeea: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 16; - case 0xaeeb: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 24; + case 0xaee8: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask & 0xff; + case 0xaee9: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 8; + case 0xaeea: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 16; + case 0xaeeb: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 24; - case 0xb2e8: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp & 0xff; - case 0xb2e9: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 8; - case 0xb2ea: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 16; - case 0xb2eb: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 24; + case 0xb2e8: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp & 0xff; + case 0xb2e9: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 8; + case 0xb2ea: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 16; + case 0xb2eb: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 24; - case 0xb6e8: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_mix; + case 0xb6e8: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_mix; - case 0xbae8: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_mix; + case 0xbae8: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_mix; - case 0xbee8: - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] & 0xff; - case 0x1: return s3->accel.multifunc[0x1] & 0xff; - case 0x2: return s3->accel.multifunc[0x2] & 0xff; - case 0x3: return s3->accel.multifunc[0x3] & 0xff; - case 0x4: return s3->accel.multifunc[0x4] & 0xff; - case 0x5: return s3->accel.multifunc[0xa] & 0xff; - case 0x6: return s3->accel.multifunc[0xe] & 0xff; - case 0x7: return s3->accel.cmd & 0xff; - case 0x8: return s3->accel.subsys_cntl & 0xff; - case 0x9: return s3->accel.setup_md & 0xff; - case 0xa: return s3->accel.multifunc[0xd] & 0xff; - } - return 0xff; - case 0xbee9: - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf]++; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] >> 8; - case 0x1: return s3->accel.multifunc[0x1] >> 8; - case 0x2: return s3->accel.multifunc[0x2] >> 8; - case 0x3: return s3->accel.multifunc[0x3] >> 8; - case 0x4: return s3->accel.multifunc[0x4] >> 8; - case 0x5: return s3->accel.multifunc[0xa] >> 8; - case 0x6: return s3->accel.multifunc[0xe] >> 8; - case 0x7: return s3->accel.cmd >> 8; - case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000; - case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000; - case 0xa: return s3->accel.multifunc[0xd] >> 8; - } - return 0xff; + case 0xbee8: + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + switch (temp) + { + case 0x0: return s3->accel.multifunc[0x0] & 0xff; + case 0x1: return s3->accel.multifunc[0x1] & 0xff; + case 0x2: return s3->accel.multifunc[0x2] & 0xff; + case 0x3: return s3->accel.multifunc[0x3] & 0xff; + case 0x4: return s3->accel.multifunc[0x4] & 0xff; + case 0x5: return s3->accel.multifunc[0xa] & 0xff; + case 0x6: return s3->accel.multifunc[0xe] & 0xff; + case 0x7: return s3->accel.cmd & 0xff; + case 0x8: return s3->accel.subsys_cntl & 0xff; + case 0x9: return s3->accel.setup_md & 0xff; + case 0xa: return s3->accel.multifunc[0xd] & 0xff; + } + return 0xff; + case 0xbee9: + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + s3->accel.multifunc[0xf]++; + switch (temp) + { + case 0x0: return s3->accel.multifunc[0x0] >> 8; + case 0x1: return s3->accel.multifunc[0x1] >> 8; + case 0x2: return s3->accel.multifunc[0x2] >> 8; + case 0x3: return s3->accel.multifunc[0x3] >> 8; + case 0x4: return s3->accel.multifunc[0x4] >> 8; + case 0x5: return s3->accel.multifunc[0xa] >> 8; + case 0x6: return s3->accel.multifunc[0xe] >> 8; + case 0x7: return s3->accel.cmd >> 8; + case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000; + case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000; + case 0xa: return s3->accel.multifunc[0xd] >> 8; + } + return 0xff; - case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/ - break; - } - return 0; + case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/ + break; + } + return 0; } void s3_accel_write(uint32_t addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); } void s3_accel_write_w(uint32_t addr, uint16_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); } void s3_accel_write_l(uint32_t addr, uint32_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); } uint8_t s3_accel_read(uint32_t addr, void *p) { - if (addr & 0x8000) - return s3_accel_in(addr & 0xffff, p); - return 0; + if (addr & 0x8000) + return s3_accel_in(addr & 0xffff, p); + return 0; } static void polygon_setup(s3_t *s3) { - if (s3->accel.point_1_updated) - { - int start_x = s3->accel.poly_cx; - int start_y = s3->accel.poly_cy; - int end_x = s3->accel.destx_distp << 20; - int end_y = s3->accel.desty_axstp; - - if (end_y - start_y) - s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); - else - s3->accel.poly_dx1 = 0; - - s3->accel.point_1_updated = 0; + if (s3->accel.point_1_updated) + { + int start_x = s3->accel.poly_cx; + int start_y = s3->accel.poly_cy; + int end_x = s3->accel.destx_distp << 20; + int end_y = s3->accel.desty_axstp; + + if (end_y - start_y) + s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx1 = 0; + + s3->accel.point_1_updated = 0; - if (end_y == s3->accel.poly_cy) - { - s3->accel.poly_cx = end_x; - s3->accel.poly_x = end_x >> 20; - } - } - if (s3->accel.point_2_updated) - { - int start_x = s3->accel.poly_cx2; - int start_y = s3->accel.poly_cy2; - int end_x = s3->accel.x2 << 20; - int end_y = s3->accel.desty_axstp2; + if (end_y == s3->accel.poly_cy) + { + s3->accel.poly_cx = end_x; + s3->accel.poly_x = end_x >> 20; + } + } + if (s3->accel.point_2_updated) + { + int start_x = s3->accel.poly_cx2; + int start_y = s3->accel.poly_cy2; + int end_x = s3->accel.x2 << 20; + int end_y = s3->accel.desty_axstp2; - if (end_y - start_y) - s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); - else - s3->accel.poly_dx2 = 0; + if (end_y - start_y) + s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx2 = 0; - s3->accel.point_2_updated = 0; - - if (end_y == s3->accel.poly_cy) - s3->accel.poly_cx2 = end_x; - } + s3->accel.point_2_updated = 0; + + if (end_y == s3->accel.poly_cy) + s3->accel.poly_cx2 = end_x; + } } #define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \ - if (vram_mask) \ - dat = ((dat & rd_mask) == rd_mask); + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \ + if (vram_mask) \ + dat = ((dat & rd_mask) == rd_mask); #define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; -#define MIX { \ - uint32_t old_dest_dat = dest_dat; \ - switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ - { \ - case 0x0: dest_dat = ~dest_dat; break; \ - case 0x1: dest_dat = 0; break; \ - case 0x2: dest_dat = ~0; break; \ - case 0x3: dest_dat = dest_dat; break; \ - case 0x4: dest_dat = ~src_dat; break; \ - case 0x5: dest_dat = src_dat ^ dest_dat; break; \ - case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ - case 0x7: dest_dat = src_dat; break; \ - case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ - case 0x9: dest_dat = ~src_dat | dest_dat; break; \ - case 0xa: dest_dat = src_dat | ~dest_dat; break; \ - case 0xb: dest_dat = src_dat | dest_dat; break; \ - case 0xc: dest_dat = src_dat & dest_dat; break; \ - case 0xd: dest_dat = src_dat & ~dest_dat; break; \ - case 0xe: dest_dat = ~src_dat & dest_dat; break; \ - case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ - } \ - dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ - } +#define MIX { \ + uint32_t old_dest_dat = dest_dat; \ + switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ + { \ + case 0x0: dest_dat = ~dest_dat; break; \ + case 0x1: dest_dat = 0; break; \ + case 0x2: dest_dat = ~0; break; \ + case 0x3: dest_dat = dest_dat; break; \ + case 0x4: dest_dat = ~src_dat; break; \ + case 0x5: dest_dat = src_dat ^ dest_dat; break; \ + case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ + case 0x7: dest_dat = src_dat; break; \ + case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ + case 0x9: dest_dat = ~src_dat | dest_dat; break; \ + case 0xa: dest_dat = src_dat | ~dest_dat; break; \ + case 0xb: dest_dat = src_dat | dest_dat; break; \ + case 0xc: dest_dat = src_dat & dest_dat; break; \ + case 0xd: dest_dat = src_dat & ~dest_dat; break; \ + case 0xe: dest_dat = ~src_dat & dest_dat; break; \ + case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ + } \ + dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } -#define WRITE(addr) if (s3->bpp == 0) \ - { \ - svga->vram[(addr) & s3->vram_mask] = dest_dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ - } \ - else if (s3->bpp == 1) \ - { \ - vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ - } \ - else \ - { \ - vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ - } +#define WRITE(addr) if (s3->bpp == 0) \ + { \ + svga->vram[(addr) & s3->vram_mask] = dest_dat; \ + svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + } \ + else if (s3->bpp == 1) \ + { \ + vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ + svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ + } \ + else \ + { \ + vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ + svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ + } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { - svga_t *svga = &s3->svga; - uint32_t src_dat = 0, dest_dat; - int frgd_mix, bkgd_mix; - int clip_t = s3->accel.multifunc[1] & 0xfff; - int clip_l = s3->accel.multifunc[2] & 0xfff; - int clip_b = s3->accel.multifunc[3] & 0xfff; - int clip_r = s3->accel.multifunc[4] & 0xfff; - int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; - uint32_t mix_mask = 0; - uint16_t *vram_w = (uint16_t *)svga->vram; - uint32_t *vram_l = (uint32_t *)svga->vram; - uint32_t compare = s3->accel.color_cmp; - int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; - uint32_t rd_mask = s3->accel.rd_mask; - int cmd = s3->accel.cmd >> 13; - - if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11))) - cmd |= 8; + svga_t *svga = &s3->svga; + uint32_t src_dat = 0, dest_dat; + int frgd_mix, bkgd_mix; + int clip_t = s3->accel.multifunc[1] & 0xfff; + int clip_l = s3->accel.multifunc[2] & 0xfff; + int clip_b = s3->accel.multifunc[3] & 0xfff; + int clip_r = s3->accel.multifunc[4] & 0xfff; + int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; + uint32_t mix_mask = 0; + uint16_t *vram_w = (uint16_t *)svga->vram; + uint32_t *vram_l = (uint32_t *)svga->vram; + uint32_t compare = s3->accel.color_cmp; + int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; + uint32_t rd_mask = s3->accel.rd_mask; + int cmd = s3->accel.cmd >> 13; + + if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + cmd |= 8; - if (!cpu_input) s3->accel.dat_count = 0; - if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) - { - if (s3->bpp == 3 && count == 2) - { - if (s3->accel.dat_count) - { - cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; - count = 4; - s3->accel.dat_count = 0; - } - else - { - s3->accel.dat_buf = cpu_dat & 0xffff; - s3->accel.dat_count = 1; - } - } - if (s3->bpp == 1) count >>= 1; - if (s3->bpp == 3) count >>= 2; - } + if (!cpu_input) s3->accel.dat_count = 0; + if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) + { + if (s3->bpp == 3 && count == 2) + { + if (s3->accel.dat_count) + { + cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; + count = 4; + s3->accel.dat_count = 0; + } + else + { + s3->accel.dat_buf = cpu_dat & 0xffff; + s3->accel.dat_count = 1; + } + } + if (s3->bpp == 1) count >>= 1; + if (s3->bpp == 3) count >>= 2; + } - if (s3->bpp == 0) - rd_mask &= 0xff; - else if (s3->bpp == 1) - rd_mask &= 0xffff; + if (s3->bpp == 0) + rd_mask &= 0xff; + else if (s3->bpp == 1) + rd_mask &= 0xffff; - switch (s3->accel.cmd & 0x600) - { - case 0x000: mix_mask = 0x80; break; - case 0x200: mix_mask = 0x8000; break; - case 0x400: mix_mask = 0x80000000; break; - case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break; - } + switch (s3->accel.cmd & 0x600) + { + case 0x000: mix_mask = 0x80; break; + case 0x200: mix_mask = 0x8000; break; + case 0x400: mix_mask = 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break; + } - if (s3->bpp == 0) compare &= 0xff; - if (s3->bpp == 1) compare &= 0xffff; - switch (cmd) - { - case 1: /*Draw line*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - s3->accel.sy = s3->accel.maj_axis_pcnt; - } + if (s3->bpp == 0) compare &= 0xff; + if (s3->bpp == 1) compare &= 0xffff; + switch (cmd) + { + case 1: /*Draw line*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + s3->accel.sy = s3->accel.maj_axis_pcnt; + } s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -1830,146 +1880,146 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } + if (s3->accel.cmd & 8) /*Radial*/ + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - MIX + MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx); - } - } + WRITE((s3->accel.cy * s3->width) + s3->accel.cx); + } + } - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.sy) - break; + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + if (!s3->accel.sy) + break; - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - else /*Bresenham*/ - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cx++; break; + case 0x20: s3->accel.cx++; s3->accel.cy--; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cx--; s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx--; s3->accel.cy++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cx++; s3->accel.cy++; break; + } + s3->accel.sy--; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + else /*Bresenham*/ + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - MIX + MIX - WRITE((s3->accel.cy * s3->width) + s3->accel.cx); - } - } + WRITE((s3->accel.cy * s3->width) + s3->accel.cx); + } + } - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - if (!s3->accel.sy) - break; + if (!s3->accel.sy) + break; - if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) - { - s3->accel.err_term += s3->accel.destx_distp; - /*Step minor axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cy--; break; - case 0x20: s3->accel.cy--; break; - case 0x40: s3->accel.cx--; break; - case 0x60: s3->accel.cx++; break; - case 0x80: s3->accel.cy++; break; - case 0xa0: s3->accel.cy++; break; - case 0xc0: s3->accel.cx--; break; - case 0xe0: s3->accel.cx++; break; - } - } - else - s3->accel.err_term += s3->accel.desty_axstp; + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) + { + s3->accel.err_term += s3->accel.destx_distp; + /*Step minor axis*/ + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cy--; break; + case 0x20: s3->accel.cy--; break; + case 0x40: s3->accel.cx--; break; + case 0x60: s3->accel.cx++; break; + case 0x80: s3->accel.cy++; break; + case 0xa0: s3->accel.cy++; break; + case 0xc0: s3->accel.cx--; break; + case 0xe0: s3->accel.cx++; break; + } + } + else + s3->accel.err_term += s3->accel.desty_axstp; - /*Step major axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx--; break; - case 0x20: s3->accel.cx++; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - break; - - case 2: /*Rectangle fill*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - s3->accel.dest = s3->accel.cy * s3->width; - } + /*Step major axis*/ + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cx--; break; + case 0x20: s3->accel.cx++; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cy++; break; + } + s3->accel.sy--; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 2: /*Rectangle fill*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + s3->accel.dest = s3->accel.cy * s3->width; + } s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -1979,86 +2029,86 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST(s3->accel.dest + s3->accel.cx, dest_dat); + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.cx, dest_dat); - MIX + MIX - WRITE(s3->accel.dest + s3->accel.cx); - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (s3->accel.cmd & 0x20) s3->accel.cx++; - else s3->accel.cx--; - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + WRITE(s3->accel.dest + s3->accel.cx); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (s3->accel.cmd & 0x20) s3->accel.cx++; + else s3->accel.cx--; + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - if (s3->accel.cmd & 0x80) s3->accel.cy++; - else s3->accel.cy--; - - s3->accel.dest = s3->accel.cy * s3->width; - s3->accel.sy--; + if (s3->accel.cmd & 0x80) s3->accel.cy++; + else s3->accel.cy--; + + s3->accel.dest = s3->accel.cy * s3->width; + s3->accel.sy--; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - { + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + { s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; - return; - } - } - } - break; + return; + } + } + } + break; - case 6: /*BitBlt*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + case 6: /*BitBlt*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + s3->accel.cx = s3->accel.cur_x & 0xfff; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; - } + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + } s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -2068,168 +2118,168 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - if (s3->accel.sy < 0) - return; + if (s3->accel.sy < 0) + return; - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && - (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && + (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) - { - while (1) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - READ_SRC(s3->accel.src + s3->accel.cx, src_dat); - READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); + { + while (1) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + READ_SRC(s3->accel.src + s3->accel.cx, src_dat); + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); + dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); - WRITE(s3->accel.dest + s3->accel.dx); - } - - s3->accel.cx++; - s3->accel.dx++; - s3->accel.sx--; - if (s3->accel.sx < 0) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - s3->accel.cy++; - s3->accel.dy++; - - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; - - s3->accel.sy--; - - if (s3->accel.sy < 0) - { - return; - } - } - } - } - else - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - if (vram_mask) - { - READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; - } + WRITE(s3->accel.dest + s3->accel.dx); + } + + s3->accel.cx++; + s3->accel.dx++; + s3->accel.sx--; + if (s3->accel.sx < 0) + { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + s3->accel.cy++; + s3->accel.dy++; + + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (s3->accel.sy < 0) + { + return; + } + } + } + } + else + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - MIX + MIX - WRITE(s3->accel.dest + s3->accel.dx); - } - } + WRITE(s3->accel.dest + s3->accel.dx); + } + } - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - if (s3->accel.cmd & 0x20) - { - s3->accel.cx++; - s3->accel.dx++; - } - else - { - s3->accel.cx--; - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + if (s3->accel.cmd & 0x20) + { + s3->accel.cx++; + s3->accel.dx++; + } + else + { + s3->accel.cx--; + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) + { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + else + { + s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - if (s3->accel.cmd & 0x80) - { - s3->accel.cy++; - s3->accel.dy++; - } - else - { - s3->accel.cy--; - s3->accel.dy--; - } + if (s3->accel.cmd & 0x80) + { + s3->accel.cy++; + s3->accel.dy++; + } + else + { + s3->accel.cy--; + s3->accel.dy--; + } - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; - s3->accel.sy--; + s3->accel.sy--; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - { - return; - } - } - } - } - break; + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + { + return; + } + } + } + } + break; - case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - /*Align source with destination*/ - s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; - s3->accel.dest = s3->accel.dy * s3->width; - - s3->accel.cx = s3->accel.dx & 7; - s3->accel.cy = s3->accel.dy & 7; - - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); - } + s3->accel.cx = s3->accel.cur_x & 0xfff; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + /*Align source with destination*/ + s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.cx = s3->accel.dx & 7; + s3->accel.cy = s3->accel.dy & 7; + + s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); + } s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -2239,102 +2289,102 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - if (vram_mask) - { - READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; - } + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - MIX + MIX - WRITE(s3->accel.dest + s3->accel.dx); - } - } + WRITE(s3->accel.dest + s3->accel.dx); + } + } - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx++; - } - else - { - s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + if (s3->accel.cmd & 0x20) + { + s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx++; + } + else + { + s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) + { + s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + else + { + s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); + s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - if (s3->accel.cmd & 0x80) - { - s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy++; - } - else - { - s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy--; - } + if (s3->accel.cmd & 0x80) + { + s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy++; + } + else + { + s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy--; + } - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); - s3->accel.dest = s3->accel.dy * s3->width; + s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); + s3->accel.dest = s3->accel.dy * s3->width; - s3->accel.sy--; + s3->accel.sy--; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - return; - } - } - break; + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + return; + } + } + break; - case 3: /*Polygon Fill Solid (Trio64 only)*/ - { - int end_y1, end_y2; - - if (s3->chip != S3_TRIO64) - break; + case 3: /*Polygon Fill Solid (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; - polygon_setup(s3); + polygon_setup(s3); s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -2344,79 +2394,79 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - end_y1 = s3->accel.desty_axstp; - end_y2 = s3->accel.desty_axstp2; + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) - { - int y = s3->accel.poly_cy; - int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - s3->accel.dest = y * s3->width; - - while (x_count-- && count--) - { - if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && - s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) - { - switch (frgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; /*Nor supported?*/ break; - } + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + switch (frgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; /*Nor supported?*/ break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); - - MIX + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX - WRITE(s3->accel.dest + s3->accel.poly_x); - } - } - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) - s3->accel.poly_x++; - else - s3->accel.poly_x--; - } - - s3->accel.poly_cx += s3->accel.poly_dx1; - s3->accel.poly_cx2 += s3->accel.poly_dx2; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - - s3->accel.poly_cy++; - s3->accel.poly_cy2++; - - if (!count) - break; - } - - s3->accel.cur_x = s3->accel.poly_cx & 0xfff; - s3->accel.cur_y = s3->accel.poly_cy & 0xfff; - s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; - } - break; + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; - case 11: /*Polygon Fill Pattern (Trio64 only)*/ - { - int end_y1, end_y2; - - if (s3->chip != S3_TRIO64) - break; + case 11: /*Polygon Fill Pattern (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; - polygon_setup(s3); + polygon_setup(s3); s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ @@ -2426,319 +2476,417 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat return; /*Wait for data from CPU*/ } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - - end_y1 = s3->accel.desty_axstp; - end_y2 = s3->accel.desty_axstp2; + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) - { - int y = s3->accel.poly_cy; - int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; - s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width); - s3->accel.dest = y * s3->width; - - while (x_count-- && count--) - { - int pat_x = s3->accel.poly_x & 7; - - if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && - s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) - { - if (vram_mask) - { - READ_SRC(s3->accel.src + pat_x, mix_dat) - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break; - } + s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width); + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + int pat_x = s3->accel.poly_x & 7; + + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + pat_x, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); - - MIX + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX - WRITE(s3->accel.dest + s3->accel.poly_x); - } - } - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - mix_dat <<= 1; - mix_dat |= 1; + mix_dat <<= 1; + mix_dat |= 1; - if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) - s3->accel.poly_x++; - else - s3->accel.poly_x--; - } - - s3->accel.poly_cx += s3->accel.poly_dx1; - s3->accel.poly_cx2 += s3->accel.poly_dx2; - s3->accel.poly_x = s3->accel.poly_cx >> 20; - - s3->accel.poly_cy++; - s3->accel.poly_cy2++; - - if (!count) - break; - } - - s3->accel.cur_x = s3->accel.poly_cx & 0xfff; - s3->accel.cur_y = s3->accel.poly_cy & 0xfff; - s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; - } - break; - } + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + } } void s3_hwcursor_draw(svga_t *svga, int displine) { s3_t *s3 = (s3_t *)svga->p; - int x; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int x; + uint16_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; int y_add, x_add; - uint32_t fg = 0, bg = 0; + uint32_t fg, bg; y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - - switch (svga->bpp) - { - case 15: - fg = video_15to32[s3->hwc_fg_col & 0xffff]; - bg = video_15to32[s3->hwc_bg_col & 0xffff]; - break; - - case 16: - fg = video_16to32[s3->hwc_fg_col & 0xffff]; - bg = video_16to32[s3->hwc_bg_col & 0xffff]; - break; - - case 24: case 32: - fg = s3->hwc_fg_col; - bg = s3->hwc_bg_col; - break; - default: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - { - fg = svga->pallook[s3->hwc_fg_col & 0xff]; - bg = svga->pallook[s3->hwc_bg_col & 0xff]; - } - else - { - fg = svga->pallook[svga->crtc[0xe]]; - bg = svga->pallook[svga->crtc[0xf]]; - } - break; - } + switch (svga->bpp) + { + case 15: + fg = video_15to32[s3->hwc_fg_col & 0xffff]; + bg = video_15to32[s3->hwc_bg_col & 0xffff]; + break; + + case 16: + fg = video_16to32[s3->hwc_fg_col & 0xffff]; + bg = video_16to32[s3->hwc_bg_col & 0xffff]; + break; + + case 24: case 32: + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + break; - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + default: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + { + fg = svga->pallook[s3->hwc_fg_col & 0xff]; + bg = svga->pallook[s3->hwc_bg_col & 0xff]; + } + else + { + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; + } + break; + } - for (x = 0; x < 64; x += 16) - { - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; - for (xx = 0; xx < 16; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x8000)) - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; - else if (dat[1] & 0x8000) - ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr += 4; - } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + for (x = 0; x < 64; x += 16) + { + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + for (xx = 0; xx < 16; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (!(dat[0] & 0x8000)) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + else if (dat[1] & 0x8000) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr += 4; + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } +void s3_bt485_hwcursor_draw(svga_t *svga, int displine) +{ + s3_t *s3 = (s3_t *)svga->p; + int x, xx, comb, b0, b1; + uint16_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; + int pitch, bppl, mode, x_pos, y_pos; + uint32_t clr1, clr2, clr3, *p; + uint8_t *cd; + + clr1 = s3->bt485_ramdac.extpallook[1]; + clr2 = s3->bt485_ramdac.extpallook[2]; + clr3 = s3->bt485_ramdac.extpallook[3]; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + + /* The planes come in two parts, and each plane is 1bpp, + so a 32x32 cursor has 4 bytes per line, and a 64x64 + cursor has 8 bytes per line. */ + pitch = (svga->hwcursor_latch.xsize >> 3); /* Bytes per line. */ + /* A 32x32 cursor has 128 bytes per line, and a 64x64 + cursor has 512 bytes per line. */ + bppl = (pitch * svga->hwcursor_latch.ysize); /* Bytes per plane. */ + mode = s3->bt485_ramdac.cr2 & 0x03; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; + + if (svga->hwcursor_latch.xsize == 64) + cd = (uint8_t *) s3->bt485_ramdac.cursor64_data; + else + cd = (uint8_t *) s3->bt485_ramdac.cursor32_data; + + for (x = 0; x < svga->hwcursor_latch.xsize; x += 16) { + dat[0] = (cd[svga->hwcursor_latch.addr] << 8) | + cd[svga->hwcursor_latch.addr + 1]; + dat[1] = (cd[svga->hwcursor_latch.addr + bppl] << 8) | + cd[svga->hwcursor_latch.addr + bppl + 1]; + + for (xx = 0; xx < 16; xx++) { + b0 = (dat[0] >> (15 - xx)) & 1; + b1 = (dat[1] >> (15 - xx)) & 1; + comb = (b0 | (b1 << 1)); + + y_pos = displine + y_add; + x_pos = offset + 32 + x_add; + p = ((uint32_t *)buffer32->line[y_pos]); + + if (offset >= svga->hwcursor_latch.x) { + switch (mode) { + case 1: /* Three Color */ + switch (comb) { + case 1: + p[x_pos] = clr1; + break; + case 2: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] = clr3; + break; + } + break; + case 2: /* PM/Windows */ + switch (comb) { + case 0: + p[x_pos] = clr1; + break; + case 1: + p[x_pos] = clr2; + break; + case 3: + p[x_pos] ^= 0xffffff; + break; + } + break; + case 3: /* X-Windows */ + switch (comb) { + case 2: + p[x_pos] = clr1; + break; + case 3: + p[x_pos] = clr2; + break; + } + break; + } + } + offset++; + } + svga->hwcursor_latch.addr += 2; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; +} static void s3_io_remove(s3_t *s3) { - io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - - io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64) - { - io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - else - { - io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - } - io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + + io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_TRIO64) + { + io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + else + { + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } static void s3_io_set(s3_t *s3) { - s3_io_remove(s3); + s3_io_remove(s3); - io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - - io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + + io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } - + uint8_t s3_pci_read(int func, int addr, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; - - case 0x02: return s3->id_ext_pci; - case 0x03: return 0x88; - - case PCI_REG_COMMAND: - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + switch (addr) + { + case 0x00: return 0x33; /*'S3'*/ + case 0x01: return 0x53; + + case 0x02: return s3->id_ext_pci; + case 0x03: return 0x88; + + case PCI_REG_COMMAND: + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x00; /*Supports VGA interface*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return svga->crtc[0x5a] & 0x80; - case 0x13: return svga->crtc[0x59]; + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x00; /*Supports VGA interface*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return svga->crtc[0x5a] & 0x80; + case 0x13: return svga->crtc[0x59]; - case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; - case 0x33: return s3->has_bios ? s3->pci_regs[0x33] : 0x00; - - case 0x3c: return s3->int_line; - case 0x3d: return PCI_INTA; - } - return 0; + case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; + case 0x33: return s3->has_bios ? s3->pci_regs[0x33] : 0x00; + + case 0x3c: return s3->int_line; + case 0x3d: return PCI_INTA; + } + return 0; } void s3_pci_write(int func, int addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case PCI_REG_COMMAND: - s3->pci_regs[PCI_REG_COMMAND] = val & 0x23; - if (val & PCI_COMMAND_IO) - s3_io_set(s3); - else - s3_io_remove(s3); - s3_updatemapping(s3); - break; - - case 0x12: - svga->crtc[0x5a] = val & 0x80; - s3_updatemapping(s3); - break; - case 0x13: - svga->crtc[0x59] = val; - s3_updatemapping(s3); - break; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + switch (addr) + { + case PCI_REG_COMMAND: + s3->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) + s3_io_set(s3); + else + s3_io_remove(s3); + s3_updatemapping(s3); + break; + + case 0x12: + svga->crtc[0x5a] = val & 0x80; + s3_updatemapping(s3); + break; + case 0x13: + svga->crtc[0x59] = val; + s3_updatemapping(s3); + break; - case 0x30: case 0x32: case 0x33: + case 0x30: case 0x32: case 0x33: if (!s3->has_bios) return; - s3->pci_regs[addr] = val; - if (s3->pci_regs[0x30] & 0x01) - { - uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); - mem_mapping_set_addr(&s3->bios_rom.mapping, addr, 0x8000); - } - else - { - mem_mapping_disable(&s3->bios_rom.mapping); - } - return; - - case 0x3c: - s3->int_line = val; - return; - } + s3->pci_regs[addr] = val; + if (s3->pci_regs[0x30] & 0x01) + { + uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); + mem_mapping_set_addr(&s3->bios_rom.mapping, addr, 0x8000); + } + else + { + mem_mapping_disable(&s3->bios_rom.mapping); + } + return; + + case 0x3c: + s3->int_line = val; + return; + } } static int vram_sizes[] = { - 7, /*512 kB*/ - 6, /*1 MB*/ - 4, /*2 MB*/ - 0, - 0, /*4 MB*/ - 0, - 0, - 0, - 3 /*8 MB*/ + 7, /*512 kB*/ + 6, /*1 MB*/ + 4, /*2 MB*/ + 0, + 0, /*4 MB*/ + 0, + 0, + 0, + 3 /*8 MB*/ }; static void *s3_init(const device_t *info) @@ -2746,9 +2894,9 @@ static void *s3_init(const device_t *info) const wchar_t *bios_fn; int chip, stepping; s3_t *s3 = malloc(sizeof(s3_t)); - svga_t *svga = &s3->svga; - int vram; - uint32_t vram_size; + svga_t *svga = &s3->svga; + int vram; + uint32_t vram_size; switch(info->local) { case S3_PARADISE_BAHAMAS64: @@ -2761,10 +2909,10 @@ static void *s3_init(const device_t *info) chip = S3_VISION864; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864); break; - case S3_EXPERTCOLOR_DSV3868P_CF55: - bios_fn = ROM_EXPERTCOLOR_DSV3868P_CF55; - chip = S3_VISION868; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868); + case S3_DIAMOND_STEALTH64_964: + bios_fn = ROM_DIAMOND_STEALTH64_964; + chip = S3_VISION964; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964); break; case S3_PHOENIX_TRIO32: bios_fn = ROM_PHOENIX_TRIO32; @@ -2781,8 +2929,8 @@ static void *s3_init(const device_t *info) chip = S3_TRIO64; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_trio64); break; - case S3_DIAMOND_STEALTH64: - bios_fn = ROM_DIAMOND_STEALTH64; + case S3_DIAMOND_STEALTH64_764: + bios_fn = ROM_DIAMOND_STEALTH64_764; chip = S3_TRIO64; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_stealth64); break; @@ -2798,6 +2946,7 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); vram = device_get_config_int("memory"); + if (vram) vram_size = vram << 20; else @@ -2827,12 +2976,19 @@ static void *s3_init(const device_t *info) NULL, MEM_MAPPING_EXTERNAL, s3); mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - - svga_init(&s3->svga, s3, vram_size, - s3_recalctimings, - s3_in, s3_out, - s3_hwcursor_draw, - NULL); + + if (chip == S3_VISION964) + svga_init(&s3->svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + s3_bt485_hwcursor_draw, + NULL); + else + svga_init(&s3->svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + s3_hwcursor_draw, + NULL); switch (vram) { case 0: /* 512 kB */ @@ -2869,9 +3025,9 @@ static void *s3_init(const device_t *info) svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); svga->crtc[0x37] = 1 | (7 << 5); - svga->vblank_start = s3_vblank_start; + svga->vblank_start = s3_vblank_start; - s3_io_set(s3); + s3_io_set(s3); if (info->flags & DEVICE_PCI) s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); @@ -2907,18 +3063,18 @@ static void *s3_init(const device_t *info) sdac_init(&s3->ramdac); break; - case S3_EXPERTCOLOR_DSV3868P_CF55: + case S3_DIAMOND_STEALTH64_964: svga->decode_mask = (8 << 20) - 1; - s3->id = 0xe1; /*Vision868*/ - s3->id_ext = 0x90; - s3->id_ext_pci = 0x80; + s3->id = 0xd1; /*Vision964P*/ + s3->id_ext = 0xd1; + s3->id_ext_pci = 0xd1; s3->packed_mmio = 1; - - s3->getclock = sdac_getclock; - s3->getclock_p = &s3->ramdac; - sdac_init(&s3->ramdac); - break; - + + icd2061_init(&s3->icd2061); + s3->getclock = icd2061_getclock; + s3->getclock_p = &s3->icd2061; + break; + case S3_PHOENIX_TRIO32: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio32*/ @@ -2932,7 +3088,7 @@ static void *s3_init(const device_t *info) case S3_PHOENIX_TRIO64: case S3_PHOENIX_TRIO64_ONBOARD: - case S3_DIAMOND_STEALTH64: + case S3_DIAMOND_STEALTH64_764: if (device_get_config_int("memory") == 1) s3->svga.vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ /* Fall over. */ @@ -2956,393 +3112,366 @@ static void *s3_init(const device_t *info) static int s3_bahamas64_available(void) { - return rom_present(ROM_PARADISE_BAHAMAS64); + return rom_present(ROM_PARADISE_BAHAMAS64); } static int s3_phoenix_vision864_available(void) { - return rom_present(ROM_PHOENIX_VISION864); + return rom_present(ROM_PHOENIX_VISION864); } -static int s3_expertcolor_dsv3868p_cf55_available(void) +static int s3_diamond_stealth64_964_available(void) { - return rom_present(ROM_EXPERTCOLOR_DSV3868P_CF55); + return rom_present(ROM_DIAMOND_STEALTH64_964); } static int s3_phoenix_trio32_available(void) { - return rom_present(ROM_PHOENIX_TRIO32); + return rom_present(ROM_PHOENIX_TRIO32); } static int s3_9fx_available(void) { - return rom_present(ROM_NUMBER9_9FX); + return rom_present(ROM_NUMBER9_9FX); } static int s3_phoenix_trio64_available(void) { - return rom_present(ROM_PHOENIX_TRIO64); + return rom_present(ROM_PHOENIX_TRIO64); } -static int s3_diamond_stealth64_available(void) +static int s3_diamond_stealth64_764_available(void) { - return rom_present(ROM_DIAMOND_STEALTH64); + return rom_present(ROM_DIAMOND_STEALTH64_764); } static void s3_close(void *p) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *)p; - svga_close(&s3->svga); - - thread_kill(s3->fifo_thread); - thread_destroy_event(s3->wake_fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); + svga_close(&s3->svga); + + thread_kill(s3->fifo_thread); + thread_destroy_event(s3->wake_fifo_thread); + thread_destroy_event(s3->fifo_not_full_event); - free(s3); + free(s3); } static void s3_speed_changed(void *p) { - s3_t *s3 = (s3_t *)p; - - svga_recalctimings(&s3->svga); + s3_t *s3 = (s3_t *)p; + + svga_recalctimings(&s3->svga); } static void s3_force_redraw(void *p) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *)p; - s3->svga.fullchange = changeframecount; + s3->svga.fullchange = changeframecount; } static const device_config_t s3_9fx_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t s3_phoenix_trio32_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, - { - { - "512 KB", 0 - }, - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, + { + { + "512 KB", 0 + }, + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t s3_phoenix_trio64_onboard_config[] = { - { - "memory", "Video memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Video memory size", CONFIG_SELECTION, "", 4, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t s3_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - -static const device_config_t s3_expertcolor_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "8 MB", 8 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 4, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; const device_t s3_bahamas64_vlb_device = { - "Paradise Bahamas 64 (S3 Vision864) VLB", - DEVICE_VLB, + "Paradise Bahamas 64 (S3 Vision864) VLB", + DEVICE_VLB, S3_PARADISE_BAHAMAS64, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_bahamas64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_bahamas64_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_bahamas64_pci_device = { - "Paradise Bahamas 64 (S3 Vision864) PCI", - DEVICE_PCI, + "Paradise Bahamas 64 (S3 Vision864) PCI", + DEVICE_PCI, S3_PARADISE_BAHAMAS64, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_bahamas64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_bahamas64_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; -const device_t s3_expertcolor_vlb_device = +const device_t s3_diamond_stealth64_964_vlb_device = { - "ExpertColor DSV3868P CF55 (S3 Vision868) VLB", - DEVICE_VLB, - S3_EXPERTCOLOR_DSV3868P_CF55, - s3_init, - s3_close, + "S3 Vision964 (Diamond Stealth64 VRAM) VLB", + DEVICE_VLB, + S3_DIAMOND_STEALTH64_964, + s3_init, + s3_close, NULL, - s3_expertcolor_dsv3868p_cf55_available, - s3_speed_changed, - s3_force_redraw, - s3_expertcolor_config + s3_diamond_stealth64_964_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; -const device_t s3_expertcolor_pci_device = +const device_t s3_diamond_stealth64_964_pci_device = { - "ExpertColor DSV3868P CF55 (S3 Vision868) PCI", - DEVICE_PCI, - S3_EXPERTCOLOR_DSV3868P_CF55, - s3_init, - s3_close, + "S3 Vision964 (Diamond Stealth64 VRAM) PCI", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_964, + s3_init, + s3_close, NULL, - s3_expertcolor_dsv3868p_cf55_available, - s3_speed_changed, - s3_force_redraw, - s3_expertcolor_config + s3_diamond_stealth64_964_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_9fx_vlb_device = { - "Number 9 9FX (S3 Trio64) VLB", - DEVICE_VLB, + "Number 9 9FX (S3 Trio64) VLB", + DEVICE_VLB, S3_NUMBER9_9FX, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_9fx_available, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config + s3_9fx_available, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config }; const device_t s3_9fx_pci_device = { - "Number 9 9FX (S3 Trio64) PCI", - DEVICE_PCI, + "Number 9 9FX (S3 Trio64) PCI", + DEVICE_PCI, S3_NUMBER9_9FX, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_9fx_available, - s3_speed_changed, - s3_force_redraw, - s3_9fx_config + s3_9fx_available, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config }; const device_t s3_phoenix_trio32_vlb_device = { - "Phoenix S3 Trio32 VLB", - DEVICE_VLB, + "Phoenix S3 Trio32 VLB", + DEVICE_VLB, S3_PHOENIX_TRIO32, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_trio32_available, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config + s3_phoenix_trio32_available, + s3_speed_changed, + s3_force_redraw, + s3_phoenix_trio32_config }; const device_t s3_phoenix_trio32_pci_device = { - "Phoenix S3 Trio32 PCI", - DEVICE_PCI, + "Phoenix S3 Trio32 PCI", + DEVICE_PCI, S3_PHOENIX_TRIO32, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_trio32_available, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio32_config + s3_phoenix_trio32_available, + s3_speed_changed, + s3_force_redraw, + s3_phoenix_trio32_config }; const device_t s3_phoenix_trio64_vlb_device = { - "Phoenix S3 Trio64 VLB", - DEVICE_VLB, + "Phoenix S3 Trio64 VLB", + DEVICE_VLB, S3_PHOENIX_TRIO64, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_trio64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_phoenix_trio64_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_phoenix_trio64_onboard_pci_device = { - "Phoenix S3 Trio64 On-Board PCI", - DEVICE_PCI, + "Phoenix S3 Trio64 On-Board PCI", + DEVICE_PCI, S3_PHOENIX_TRIO64_ONBOARD, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - NULL, - s3_speed_changed, - s3_force_redraw, - s3_phoenix_trio64_onboard_config + NULL, + s3_speed_changed, + s3_force_redraw, + s3_phoenix_trio64_onboard_config }; const device_t s3_phoenix_trio64_pci_device = { - "Phoenix S3 Trio64 PCI", - DEVICE_PCI, + "Phoenix S3 Trio64 PCI", + DEVICE_PCI, S3_PHOENIX_TRIO64, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_trio64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_phoenix_trio64_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_phoenix_vision864_vlb_device = { - "Phoenix S3 Vision864 VLB", - DEVICE_VLB, + "Phoenix S3 Vision864 VLB", + DEVICE_VLB, S3_PHOENIX_VISION864, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_vision864_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_phoenix_vision864_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_phoenix_vision864_pci_device = { - "Phoenix S3 Vision864 PCI", - DEVICE_PCI, + "Phoenix S3 Vision864 PCI", + DEVICE_PCI, S3_PHOENIX_VISION864, - s3_init, - s3_close, + s3_init, + s3_close, NULL, - s3_phoenix_vision864_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_phoenix_vision864_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_diamond_stealth64_vlb_device = { - "S3 Trio64 (Diamond Stealth64 DRAM) VLB", - DEVICE_PCI, - S3_DIAMOND_STEALTH64, - s3_init, - s3_close, + "S3 Trio64 (Diamond Stealth64 DRAM) VLB", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_764, + s3_init, + s3_close, NULL, - s3_diamond_stealth64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_diamond_stealth64_764_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; const device_t s3_diamond_stealth64_pci_device = { - "S3 Trio64 (Diamond Stealth64 DRAM) PCI", - DEVICE_PCI, - S3_DIAMOND_STEALTH64, - s3_init, - s3_close, + "S3 Trio64 (Diamond Stealth64 DRAM) PCI", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_764, + s3_init, + s3_close, NULL, - s3_diamond_stealth64_available, - s3_speed_changed, - s3_force_redraw, - s3_config + s3_diamond_stealth64_764_available, + s3_speed_changed, + s3_force_redraw, + s3_config }; diff --git a/src/video/vid_s3.h b/src/video/vid_s3.h index 2f4b6bd0d..8678d48d1 100644 --- a/src/video/vid_s3.h +++ b/src/video/vid_s3.h @@ -19,8 +19,6 @@ const device_t s3_bahamas64_vlb_device; const device_t s3_bahamas64_pci_device; -const device_t s3_expertcolor_vlb_device; -const device_t s3_expertcolor_pci_device; const device_t s3_9fx_vlb_device; const device_t s3_9fx_pci_device; const device_t s3_phoenix_trio32_vlb_device; @@ -32,4 +30,6 @@ const device_t s3_phoenix_vision864_pci_device; const device_t s3_phoenix_vision864_vlb_device; const device_t s3_diamond_stealth64_pci_device; const device_t s3_diamond_stealth64_vlb_device; +const device_t s3_diamond_stealth64_964_pci_device; +const device_t s3_diamond_stealth64_964_vlb_device; /* const device_t s3_miro_vision964_device; */ diff --git a/src/video/vid_table.c b/src/video/vid_table.c index c72a49e19..c716d7042 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,7 +8,7 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.38 2018/09/19 + * Version: @(#)vid_table.c 1.0.39 2018/09/30 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -124,13 +124,11 @@ video_cards[] = { {"[PCI] Cirrus Logic CL-GD 5440", "cl_gd5440_pci", &gd5440_pci_device }, {"[PCI] Cirrus Logic CL-GD 5446", "cl_gd5446_pci", &gd5446_pci_device }, {"[PCI] Cirrus Logic CL-GD 5480", "cl_gd5480_pci", &gd5480_pci_device }, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) {"[PCI] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_pci", &et4000w32p_pci_device }, -#endif {"[PCI] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_pci", &s3_virge_pci_device }, {"[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device }, {"[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device }, - {"[PCI] ExpertColor DSV3868P CF55 (S3 Vision868)", "expertcolor_pci", &s3_expertcolor_pci_device }, + {"[PCI] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, {"[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device }, {"[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device }, {"[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, @@ -145,15 +143,13 @@ video_cards[] = { {"[VLB] Cirrus Logic CL-GD 5428", "cl_gd5428_vlb", &gd5428_vlb_device }, {"[VLB] Cirrus Logic CL-GD 5429", "cl_gd5429_vlb", &gd5429_vlb_device }, {"[VLB] Cirrus Logic CL-GD 5434", "cl_gd5434_vlb", &gd5434_vlb_device }, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) {"[VLB] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_vlb", &et4000w32p_vlb_device }, -#endif {"[VLB] Diamond SpeedStar PRO (CL-GD 5426)", "cl_gd5426_vlb", &gd5426_vlb_device }, {"[VLB] Diamond SpeedStar PRO SE (CL-GD 5430)", "cl_gd5430_vlb", &gd5430_vlb_device }, {"[VLB] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_vlb", &s3_virge_vlb_device }, {"[VLB] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, {"[VLB] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, - {"[VLB] ExpertColor DSV3868P CF55 (S3 Vision868)", "expertcolor_vlb", &s3_expertcolor_vlb_device }, + {"[VLB] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, {"[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device }, {"[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device }, {"[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index b4c9517b3..fbf3c7949 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.126 2018/09/15 +# Version: @(#)Makefile.mingw 1.0.127 2018/09/30 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -62,9 +62,6 @@ ifeq ($(DEV_BUILD), y) ifndef PS2M70T4 PS2M70T4 := y endif - ifndef STEALTH32 - STEALTH32 := y - endif ifndef VNC VNC := y endif @@ -105,9 +102,6 @@ else ifndef PS2M70T4 PS2M70T4 := n endif - ifndef STEALTH32 - STEALTH32 := n - endif ifndef VGAWONDER VGAWONDER := n endif @@ -389,11 +383,6 @@ ifeq ($(PS2M70T4), y) OPTS += -DUSE_PS2M70T4 endif -ifeq ($(STEALTH32), y) -OPTS += -DUSE_STEALTH32 -DEVBROBJ += vid_icd2061.o -endif - ifeq ($(VGAWONDER), y) OPTS += -DUSE_VGAWONDER endif @@ -541,7 +530,8 @@ VIDOBJ := video.o \ vid_ati_eeprom.o \ vid_ati18800.o vid_ati28800.o \ vid_ati_mach64.o vid_ati68860_ramdac.o \ - vid_ics2595.o \ + vid_bt485_ramdac.o \ + vid_icd2061.o vid_ics2595.o \ vid_cl54xx.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \