From 5917cf0d743f63d92be6f715c3cd49ebe45cf500 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 8 Dec 2020 22:56:45 +0100 Subject: [PATCH 01/60] S3 Vision968 work. --- src/include/86box/vid_svga.h | 6 + src/include/86box/video.h | 4 + src/video/vid_ibm_rgb525_ramdac.c | 978 ++++++++++++++++++++++ src/video/vid_s3.c | 1255 +++++++++++++++++++++++++---- src/video/vid_table.c | 4 + src/win/Makefile.mingw | 2 +- 6 files changed, 2077 insertions(+), 172 deletions(-) create mode 100644 src/video/vid_ibm_rgb525_ramdac.c diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index ca7ae4c21..081f11465 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -216,6 +216,11 @@ extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t extern void bt48x_recalctimings(void *p, svga_t *svga); extern void bt48x_hwcursor_draw(svga_t *svga, int displine); +extern void ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void ibm_rgb525_recalctimings(void *p, svga_t *svga); +extern void ibm_rgb525_hwcursor_draw(svga_t *svga, int displine); + extern void icd2061_write(void *p, int val); extern float icd2061_getclock(int clock, void *p); @@ -258,6 +263,7 @@ extern const device_t bt485_ramdac_device; extern const device_t att20c505_ramdac_device; extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; +extern const device_t ibm_rgb525_ramdac_device; extern const device_t ics2494an_305_device; extern const device_t ics2595_device; extern const device_t icd2061_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 959912ac4..bc55eebcf 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -324,6 +324,10 @@ extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_vlb_device; extern const device_t s3_trio64v2_dx_pci_device; /* S3 ViRGE */ diff --git a/src/video/vid_ibm_rgb525_ramdac.c b/src/video/vid_ibm_rgb525_ramdac.c new file mode 100644 index 000000000..e6ba89e77 --- /dev/null +++ b/src/video/vid_ibm_rgb525_ramdac.c @@ -0,0 +1,978 @@ +/* + * 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. + * + * Emulation of the IBM RGB 525 true colour RAMDAC. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> + + +typedef union { + uint8_t pixel; + struct { + uint8_t b :2, g :3, r :2; + }; +} ibm_rgb525_pixel8_t; + +typedef union { + uint16_t pixel; + struct { + uint16_t b_ :5, g_ :6, r_ :5; + }; + struct { + uint16_t b :5, g :5, r :5, c :1; + }; +} ibm_rgb525_pixel16_t; + +typedef union { + uint32_t pixel; + struct { + uint8_t b, g, r, a; + }; +} ibm_rgb525_pixel32_t; + +typedef struct +{ + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t indexed_data[2048]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + uint8_t palettes[3][256]; + ibm_rgb525_pixel32_t extra_pal[4]; + int hwc_y, hwc_x; + uint16_t index, smlc_part; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status, indx_cntl; + uint8_t cursor_array; +} ibm_rgb525_ramdac_t; + + +void +ibm_rgb525_render_4bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 31)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + if (swap_nib) + dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf; + else + dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; + } else if (vram_size == 1) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + if (swap_nib) + dat = (dat64 >> ((x & 15) << 2)) & 0xf; + else + dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; + } else { + if (!(x & 7)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + if (swap_nib) + dat = (dat32 >> ((x & 7) << 2)) & 0xf; + else + dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][partition | dat]; + dat_out.g = ramdac->palettes[1][partition | dat]; + dat_out.b = ramdac->palettes[2][partition | dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 31) == 31)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + if ((vram_size == 1) && ((x & 15) == 15)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 7) == 7)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_8bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; + } else if (vram_size == 1) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 7) << 3)) & 0xff; + } else { + if (!(x & 3)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 3) << 3)) & 0xff; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][dat]; + dat_out.g = ramdac->palettes[1][dat]; + dat_out.b = ramdac->palettes[2][dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 3) == 3)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_15_16bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel16_t *dat_ex; + ibm_rgb525_pixel32_t dat_out; + uint16_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (b555_565 && (b16_dcol != 0x01)) + partition &= 0xc0; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 2) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; + } else if (vram_size == 1) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 3) << 4)) & 0xffff; + } else { + if (!(x & 1)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 1) << 4)) & 0xffff; + } + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel16_t *) &dat; + if (b555_565 && (b16_dcol != 0x01)) { + if (swaprb) { + temp = dat_ex->r_; + dat_ex->r_ = dat_ex->b_; + dat_ex->b_ = temp; + } + if (b16_dcol == 0x00) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r_]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g_]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b_]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2]; + dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_16to32[dat_ex->pixel]; + } else { + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (by16_pol) + dat ^= 0x8000; + if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g << 3]; + dat_out.b = ramdac->palettes[2][dat_ex->b << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff]; + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 7) == 7)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 3) == 3)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size && ((x & 1) == 1)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_24bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat; + uint64_t dat64[6]; + uint8_t *dat8 = (uint8_t *) dat64; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if ((x & 15) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + dat64[3] = *(uint64_t *)(&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); + dat64[4] = *(uint64_t *)(&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); + dat64[5] = *(uint64_t *)(&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL); + dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL); + dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 15) * 3)]); + } else if (vram_size == 1) { + if ((x & 7) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 7) * 3)]); + } else + dat = 0x00000000; + } else + dat = 0x00000000; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (b24_dcol == 0x00) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 48) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 24) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_32bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; + uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else if (vram_size == 1) { + if (!(x & 1)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else + dat = *(uint32_t *)(&svga->vram[svga->ma]); + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if ((b32_dcol < 0x03) && (by32_pol)) + dat ^= 0x01000000; + if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 3) == 3)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 1) == 1)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +static void +ibm_rgb525_set_bpp(ibm_rgb525_ramdac_t *ramdac, svga_t *svga) +{ + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + + if (ramdac->indexed_data[0x071] & 0x01) + switch (ramdac->indexed_data[0x00a] & 0x07) { + case 0x02: + svga->bpp = 4; + break; + case 0x03: + default: + svga->bpp = 8; + break; + case 0x04: + if (b555_565 && (b16_dcol != 0x01)) + svga->bpp = 16; + else + svga->bpp = 15; + break; + case 0x05: + svga->bpp = 24; + break; + case 0x06: + svga->bpp = 32; + break; + } else + svga->bpp = 8; + + // pclog("svga->bpp = %i\n", svga->bpp); + + svga_recalctimings(svga); +} + + +void +ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); + rs |= (!!rs2 << 2); + + // pclog("[%04X:%08X] [W] RS%01X = %02X\n", CS, cpu_state.pc, rs, val); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x03: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + index = svga->dac_addr & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->palettes[svga->dac_pos][index] = val; + else + ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2; + svga_out(addr, val, svga); + break; + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x04: + // pclog("Index low: %02X\n", val); + ramdac->index = (ramdac->index & 0x0700) | val; + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x05: + // pclog("Index high: %02X\n", val); + ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x06: + // pclog("Indexed data [%03X]: %02X\n", ramdac->index, val); + if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) + ramdac->indexed_data[ramdac->index] = val; + switch (ramdac->index) { + case 0x00a: case 0x00c: + ibm_rgb525_set_bpp(ramdac, svga); + break; + case 0x030: + switch (val & 0xc0) { + case 0x00: + ramdac->smlc_part = 0x0100; + break; + case 0x40: + ramdac->smlc_part = 0x0200; + break; + case 0x80: + ramdac->smlc_part = 0x0300; + break; + case 0xc0: + ramdac->smlc_part = 0x0400; + break; + } + svga->dac_hwcursor.addr = ramdac->smlc_part; + svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32; + svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); + /* pclog("%ix%i cursor %sabled at DAC buffer address %02X\n", svga->dac_hwcursor.xsize, + svga->dac_hwcursor.ysize, svga->dac_hwcursor.ena ? "en" : "dis", + svga->dac_hwcursor.addr); + pclog("Pixel order %i, mode %i, update %s\n", !!(ramdac->indexed_data[0x30] & 0x20), + ramdac->indexed_data[0x30] & 0x03, (ramdac->indexed_data[0x30] & 0x08) ? "now" : "later"); */ + break; + case 0x031: + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0xff00) | val; + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x032: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0x00ff) | (val << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x033: + if (!updt_cntl) + break; + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0xff00) | val; + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + break; + case 0x034: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (updt_cntl) { + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0x00ff) | (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.x); + } else { + svga->dac_hwcursor.x = ramdac->indexed_data[0x031]; + svga->dac_hwcursor.x |= (ramdac->indexed_data[0x032] << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + svga->dac_hwcursor.y = ramdac->indexed_data[0x033]; + svga->dac_hwcursor.y |= (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + } + break; + case 0x035: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.xoff = (val & 0x1f); + else + svga->dac_hwcursor.xoff = (val & 0x3f); + // pclog("Cursor X offset = %i\n", (int) svga->dac_hwcursor.xoff); + break; + case 0x036: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.yoff = (val & 0x1f); + else + svga->dac_hwcursor.yoff = (val & 0x3f); + // pclog("Cursor Y offset = %i\n", (int) svga->dac_hwcursor.yoff); + break; + case 0x040: case 0x043: case 0x046: + ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; + break; + case 0x041: case 0x044: case 0x047: + ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val; + break; + case 0x042: case 0x045: case 0x048: + ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val; + break; + case 0x060: + ramdac->extra_pal[3].r = val; + break; + case 0x061: + ramdac->extra_pal[3].g = val; + break; + case 0x062: + ramdac->extra_pal[3].b = val; + break; + case 0x071: + svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; + ibm_rgb525_set_bpp(ramdac, svga); + break; + default: + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + // pclog("Index now: %03X\n", ramdac->index); + } + break; + case 0x07: + ramdac->indx_cntl = val & 0x01; + break; + } + + return; +} + + +uint8_t +ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); + rs |= (!!rs2 << 2); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga->dac_addr & 0xff; + if (ramdac->indexed_data[0x070] & 0x20) + temp = (temp & 0xfc) | svga->dac_status; + break; + case 0x04: + temp = ramdac->index & 0xff; + break; + case 0x05: + temp = ramdac->index >> 8; + break; + case 0x06: + temp = ramdac->indexed_data[ramdac->index]; + switch (ramdac->index) { + case 0x0000: /* Revision */ + temp = 0xe0; + break; + case 0x0001: /* ID */ + temp = 0x02; + break; + case 0x0031: + if (loc_read) + temp = svga->dac_hwcursor.x & 0xff; + break; + case 0x0032: + if (loc_read) + temp = svga->dac_hwcursor.x >> 8; + break; + case 0x0033: + if (loc_read) + temp = svga->dac_hwcursor.y & 0xff; + break; + case 0x0034: + if (loc_read) + temp = svga->dac_hwcursor.y >> 8; + break; + default: + temp = ramdac->indexed_data[ramdac->index]; + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + } + break; + case 0x07: + temp = ramdac->indx_cntl; + break; + } + + // pclog("[%04X:%08X] [R] RS%01X = %02X\n", CS, cpu_state.pc, rs, temp); + + return temp; +} + + +void +ibm_rgb525_recalctimings(void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + + svga->interlace = ramdac->indexed_data[0x071] & 0x20; + + if (svga->scrblank || !svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) { + if (ramdac->indexed_data[0x071] & 0x01) { + switch (svga->bpp) { + case 4: + svga->render = ibm_rgb525_render_4bpp; + break; + case 8: + svga->render = ibm_rgb525_render_8bpp; + break; + case 15: case 16: + svga->render = ibm_rgb525_render_15_16bpp; + break; + case 24: + svga->render = ibm_rgb525_render_24bpp; + break; + case 32: + svga->render = ibm_rgb525_render_32bpp; + break; + } + } + } + } + } +} + + +void +ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) +{ + uint8_t dat, four_pixels = 0x00; + int x, pitch, x_pos, y_pos, offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + uint32_t *p; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; + uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; + + /* The planes come in one part, and each plane is 2bpp, + so a 32x32 cursor has 8 bytes per line, and a 64x64 + cursor has 16 bytes per line. */ + pitch = (svga->dac_hwcursor_latch.xsize >> 2); /* Bytes per line. */ + + if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + for (x = 0; x < svga->dac_hwcursor_latch.xsize; x ++) { + if (!(x & 3)) { + four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; + // pclog("Pixels %i to %i: %02X at %08X\n", x, x + 3, four_pixels, svga->dac_hwcursor_latch.addr); + } + if (pix_ordr) + dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; + else + dat = (four_pixels >> ((x & 3) << 1)) & 0x03; + + x_pos = offset + svga->x_add + x; + + switch (cursor_mode) { + case 0x01: + switch (dat) { + case 0x01: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x02: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Cursor Color 3 */ + p[x_pos] = ramdac->extra_pal[2].pixel; + break; + } + break; + case 0x02: + switch (dat) { + case 0x00: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x01: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Complement */ + p[x_pos] ^= 0xffffff; + break; + } + break; + case 0x03: + switch (dat) { + case 0x02: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x03: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + } + break; + } + + if ((x & 3) == 3) + svga->dac_hwcursor_latch.addr++; + } + + if ((ramdac->indexed_data[0x071] & 0x20) && !svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; +} + + +void * +ibm_rgb525_ramdac_init(const device_t *info) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) malloc(sizeof(ibm_rgb525_ramdac_t)); + memset(ramdac, 0, sizeof(ibm_rgb525_ramdac_t)); + + ramdac->smlc_part = 0x0100; + + ramdac->indexed_data[0x0008] = 0x0001; + ramdac->indexed_data[0x0015] = 0x0008; + ramdac->indexed_data[0x0016] = 0x0041; + + return ramdac; +} + + +static void +ibm_rgb525_ramdac_close(void *priv) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + + +const device_t ibm_rgb525_ramdac_device = +{ + "IBM RGB525 RAMDAC", + 0, 0, + ibm_rgb525_ramdac_init, ibm_rgb525_ramdac_close, + NULL, { NULL }, NULL, NULL, NULL +}; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 4d61f9424..dafd25ebc 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -52,6 +52,8 @@ #define ROM_TRIO64V2_DX_VBE20 L"roms/video/s3/86c775_2.bin" #define ROM_PHOENIX_TRIO64VPLUS L"roms/video/s3/64V1506.ROM" #define ROM_DIAMOND_STEALTH_SE L"roms/video/s3/DiamondStealthSE.VBI" +#define ROM_ELSAWIN2KPROX_964 L"roms/video/s3/elsaw20004m.BIN" +#define ROM_ELSAWIN2KPROX L"roms/video/s3/elsaw20008m.BIN" enum { @@ -72,7 +74,9 @@ enum S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, S3_DIAMOND_STEALTH_SE, - S3_DIAMOND_STEALTH_VRAM + S3_DIAMOND_STEALTH_VRAM, + S3_ELSAWIN2KPROX_964, + S3_ELSAWIN2KPROX }; @@ -84,11 +88,12 @@ enum S3_86C801 = 0x06, S3_86C805 = 0x07, S3_VISION964 = 0x08, - S3_VISION864 = 0x10, - S3_TRIO32 = 0x18, - S3_TRIO64 = 0x20, - S3_TRIO64V = 0x28, - S3_TRIO64V2 = 0x30 + S3_VISION968 = 0x10, + S3_VISION864 = 0x18, + S3_TRIO32 = 0x20, + S3_TRIO64 = 0x28, + S3_TRIO64V = 0x30, + S3_TRIO64V2 = 0x38 }; @@ -101,6 +106,8 @@ static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, static video_timings_t timing_s3_vision864_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_vision964_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_vision964_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_trio32_vlb = {VIDEO_BUS, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio32_pci = {VIDEO_PCI, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio64_vlb = {VIDEO_BUS, 3, 2, 4, 25, 25, 40}; @@ -176,6 +183,8 @@ typedef struct s3_t uint32_t vram_mask; uint8_t data_available; + int card_type; + struct { uint16_t subsys_cntl; @@ -183,13 +192,15 @@ typedef struct s3_t uint8_t advfunc_cntl; uint16_t cur_y, cur_y2; uint16_t cur_x, cur_x2; - uint16_t x2; + uint16_t x2, ropmix; + uint16_t pat_x, pat_y; 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 cmd, cmd2; uint16_t short_stroke; + uint32_t pat_bg_color, pat_fg_color; uint32_t bkgd_color; uint32_t frgd_color; uint32_t wrt_mask; @@ -202,12 +213,14 @@ typedef struct s3_t uint8_t pix_trans[4]; int cx, cy; + int px, py; int sx, sy; int dx, dy; uint32_t src, dest, pattern; int poly_cx, poly_cx2; int poly_cy, poly_cy2; + int poly_line_cx; int point_1_updated, point_2_updated; int poly_dx1, poly_dx2; int poly_x; @@ -300,6 +313,9 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p); static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); static uint8_t s3_accel_in(uint16_t port, void *p); +static uint8_t s3_pci_read(int func, int addr, void *p); +static void s3_pci_write(int func, int addr, uint8_t val, void *p); + static __inline void wake_fifo_thread(s3_t *s3) @@ -322,10 +338,11 @@ s3_update_irqs(s3_t *s3) if (!s3->pci) return; - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { pci_set_irq(s3->card, PCI_INTA); - else + } 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); @@ -403,26 +420,24 @@ s3_data_len(s3_t *s3) static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { - svga_t *svga = &s3->svga; - if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + } else if (s3->accel.cmd & 0x400) s3_accel_start(32, 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + else if (s3->accel.cmd & 0x400) s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); else s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); @@ -432,18 +447,18 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) -{ +{ if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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) { + } 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); @@ -459,9 +474,9 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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) { + 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 { @@ -474,9 +489,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) -{ - svga_t *svga = &s3->svga; - +{ switch (port) { case 0x8148: case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; @@ -594,11 +607,18 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.b2e8_pix = 0; break; case 0x9949: case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3_accel_start(-1, 0, 0xffffffff, 0, s3); s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ break; + case 0x994a: case 0x9aea: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff00) | val; + break; + case 0x994b: case 0x9aeb: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff) | (val << 8); + break; + case 0x9d48: case 0x9ee8: s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; @@ -802,6 +822,95 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; break; + case 0xd148: case 0xd2e8: + s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; + break; + case 0xd149: case 0xd2e9: + s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); + break; + case 0xe548: case 0xe6e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + break; + case 0xe549: case 0xe6e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xe54a: case 0xe6ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + } + break; + case 0xe54b: case 0xe6eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe948: case 0xeae8: + s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; + break; + case 0xe949: case 0xeae9: + s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); + break; + case 0xe94a: case 0xeaea: + s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; + break; + case 0xe94b: case 0xeaeb: + s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); + break; + case 0xed48: case 0xeee8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + break; + case 0xed49: case 0xeee9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xed4a: case 0xeeea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + } + break; + case 0xed4b: case 0xeeeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe148: case 0xe2e8: s3->accel.b2e8_pix = 0; if (s3_cpu_dest(s3)) @@ -831,11 +940,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } @@ -855,8 +963,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; } } @@ -887,7 +994,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { 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); @@ -940,10 +1047,17 @@ static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { svga_t *svga = &s3->svga; - + if (s3->packed_mmio) { int addr_lo = addr & 1; - switch (addr & 0xfffe) { + if (svga->crtc[0x53] & 0x08) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + s3_pci_write(0, addr & 0xff, val, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + s3_out(addr & 0xfff, val, s3); + } + + switch (addr & 0x1fffe) { case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ case 0x8102: addr = 0x86e8; break; @@ -1019,12 +1133,25 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x814a: addr = 0x96e8; break; case 0x814c: addr = 0x96ea; break; + case 0x8150: addr = 0xd2e8; break; + + case 0x8154: addr = 0x8ee8; break; + case 0x8156: addr = 0x96e8; break; + + case 0x8164: case 0x8166: + WRITE8(addr, s3->accel.pat_bg_color, val); + return; + case 0x8168: addr = 0xeae8; break; case 0x816a: addr = 0xeaea; break; + + case 0x816c: case 0x816e: + WRITE8(addr, s3->accel.pat_fg_color, val); + return; } addr |= addr_lo; } - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xffff) < 0x8000) { if (s3->accel.cmd & 0x100) { @@ -1088,7 +1215,7 @@ static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { svga_t *svga = &s3->svga; - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xfffe) < 0x8000) { s3_accel_out_pixtrans_w(s3, val); @@ -1123,7 +1250,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) if ((addr & 0xfffc) < 0x8000) { s3_accel_out_pixtrans_l(s3, val); } else { - switch (addr & 0xfffc) { + switch (addr & 0xfffc) { case 0x8180: s3->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1254,13 +1381,16 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3_accel_write_fifo(s3, addr, val); break; + case 0x18080: + break; + default: 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); break; - } + } } } else { if (addr & 0x8000) { @@ -1732,7 +1862,7 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1745,7 +1875,11 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } static void @@ -1775,7 +1909,11 @@ s3_io_remove(s3_t *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(0xd2e8, 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(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); s3_io_remove_alt(s3); } @@ -1783,13 +1921,18 @@ s3_io_remove(s3_t *s3) static void s3_io_set_alt(s3_t *s3) { + svga_t *svga = &s3->svga; + if (!s3->translate) return; + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1807,7 +1950,10 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } - io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_VISION968) + io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1821,19 +1967,30 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } } static void s3_io_set(s3_t *s3) { + svga_t *svga = &s3->svga; + s3_io_remove(s3); io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + 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); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { 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); @@ -1851,7 +2008,10 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) + io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + 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); @@ -1865,6 +2025,12 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } s3_io_set_alt(s3); } @@ -1883,7 +2049,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); } @@ -1906,6 +2072,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; + } else if (svga->seqaddr == 9) { + svga->seqregs[svga->seqaddr] = val & 0x80; + s3_io_set(s3); + return; + } else if (svga->seqaddr == 0xa) { + svga->seqregs[svga->seqaddr] = val & 0x80; + return; } break; @@ -1916,13 +2089,15 @@ s3_out(uint16_t addr, uint8_t val, void *p) rs2 = (svga->crtc[0x55] & 0x01); if (s3->chip >= S3_TRIO32) svga_out(addr, val, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) rs3 = !!(svga->crtc[0x55] & 0x02); else rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + ibm_rgb525_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) att49x_ramdac_out(addr, val, svga->ramdac, svga); else if (s3->chip < S3_86C928) sc1148x_ramdac_out(addr, val, svga->ramdac, svga); @@ -1972,7 +2147,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) 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 0x80: s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 4)) ? 1600 : 800; break; case 0x81: s3->width = 1600; break; case 0xc0: s3->width = 1280; break; } @@ -2020,13 +2195,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x45: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.ena = val & 1; break; case 0x46: case 0x47: case 0x48: case 0x49: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; @@ -2073,6 +2248,9 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x53: case 0x58: case 0x59: case 0x5a: + if (svga->crtcreg == 0x59) + pclog("0x59 write val = %02x\n", val); + s3_updatemapping(s3); break; @@ -2088,8 +2266,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) } break; + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + break; + case 0x42: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } @@ -2161,10 +2344,12 @@ s3_in(uint16_t addr, void *p) rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) return svga_in(addr, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + return ibm_rgb525_ramdac_in(addr, rs2, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) return att49x_ramdac_in(addr, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, svga->ramdac, svga); @@ -2186,18 +2371,24 @@ s3_in(uint16_t addr, void *p) 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 0x5c: /* General Output Port Register */ - temp = svga->crtc[svga->crtcreg] & 0xf0; - if (((svga->miscout >> 2) & 3) == 3) + temp = svga->crtc[svga->crtcreg] & 0xa0; + if (((svga->miscout >> 2) & 3) == 3) temp |= svga->crtc[0x42] & 0x0f; - else + else temp |= ((svga->miscout >> 2) & 3); - return temp; + if ((temp & 0xa0) == 0xa0) { + if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) + temp |= 0x40; + if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) + temp |= 0x10; + } + return temp; case 0x69: return s3->ma_ext; case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; - case 0x6c: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); + case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); } return svga->crtc[svga->crtcreg]; } @@ -2226,8 +2417,13 @@ static void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) - bt48x_recalctimings(svga->ramdac, svga); + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if (s3->card_type == S3_ELSAWIN2KPROX_964) + ibm_rgb525_recalctimings(svga->ramdac, svga); + else + bt48x_recalctimings(svga->ramdac, svga); + } else if (s3->chip == S3_VISION968) + ibm_rgb525_recalctimings(svga->ramdac, svga); else svga->interlace = svga->crtc[0x42] & 0x20; @@ -2247,36 +2443,45 @@ static void s3_recalctimings(svga_t *svga) switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; + if (s3->width == 1280) + svga->hdisp *= 2; break; case 15: svga->render = svga_render_15bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 16: svga->render = svga_render_16bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 24: svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) + if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805 && s3->chip != S3_VISION968) svga->hdisp /= 3; else svga->hdisp = (svga->hdisp * 2) / 3; break; case 32: svga->render = svga_render_32bpp_highres; - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_86C928)) + if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && + (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) svga->hdisp /= 4; + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; break; } } @@ -2467,16 +2672,23 @@ s3_updatemapping(s3_t *s3) mem_mapping_disable(&s3->linear_mapping); if (!(svga->crtc[0x53] & 0x10)) { + pclog("Linear mapping enabled at 0xa0000\n"); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; } } else { + if (s3->chip >= S3_TRIO64V) + s3->linear_base &= 0xfc000000; + else + s3->linear_base &= 0xfe000000; + pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { + pclog("Linear mapping disabled\n"); mem_mapping_disable(&s3->linear_mapping); } - + /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { mem_mapping_disable(&svga->mapping); @@ -2486,17 +2698,22 @@ s3_updatemapping(s3_t *s3) else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); } else { + pclog("Standard MMIO enabled at 0xa0000\n"); mem_mapping_enable(&s3->mmio_mapping); } } else { + pclog("Standard MMIO disabled\n"); mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { + pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - } else - mem_mapping_disable(&s3->new_mmio_mapping); + } else { + pclog("New MMIO disabled\n", s3->linear_base); + mem_mapping_disable(&s3->new_mmio_mapping); + } } } @@ -2524,7 +2741,8 @@ s3_enable_fifo(s3_t *s3) if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) + (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || + (s3->chip == S3_VISION968)) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); @@ -2535,6 +2753,7 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; @@ -2564,6 +2783,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) break; case 0x4948: case 0x4ae8: s3->accel.advfunc_cntl = val; + if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) { + s3->width = (val & 4) ? 1600 : 800; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } s3_updatemapping(s3); break; } @@ -2871,6 +3095,48 @@ s3_accel_in(uint16_t port, void *p) } break; + case 0xd148: case 0xd2e8: + return s3->accel.ropmix & 0xff; + + case 0xd149: case 0xd2e9: + return s3->accel.ropmix >> 8; + + case 0xe548: case 0xe6e8: + return s3->accel.pat_bg_color & 0xff; + + case 0xe549: case 0xe6e9: + return s3->accel.pat_bg_color >> 8; + + case 0xe54a: case 0xe6ea: + return s3->accel.pat_bg_color >> 16; + + case 0xe54b: case 0xe6eb: + return s3->accel.pat_bg_color >> 24; + + case 0xe948: case 0xeae8: + return s3->accel.pat_y & 0xff; + + case 0xe949: case 0xeae9: + return s3->accel.pat_y >> 8; + + case 0xe94a: case 0xeaea: + return s3->accel.pat_x & 0xff; + + case 0xe94b: case 0xeaeb: + return s3->accel.pat_x >> 8; + + case 0xed48: case 0xeee8: + return s3->accel.pat_fg_color & 0xff; + + case 0xed49: case 0xeee9: + return s3->accel.pat_fg_color >> 8; + + case 0xed4a: case 0xeeea: + return s3->accel.pat_fg_color >> 16; + + case 0xed4b: case 0xeeeb: + return s3->accel.pat_fg_color >> 24; + case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; @@ -2984,11 +3250,17 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) + if (!s3->enable_8514) { return 0xff; + } - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xffff) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + return s3_pci_read(0, addr & 0xff, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + return s3_in(addr & 0xfff, s3); + + switch (addr & 0x1ffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: @@ -3006,6 +3278,9 @@ s3_accel_read(uint32_t addr, void *p) return s3->subsys_stat; case 0x8505: return s3->subsys_cntl; + /* Video engine status - currently a dummy. */ + case 0x1809c: case 0x1809d: case 0x1809e: case 0x1809f: + return 0x00; default: return s3_accel_in(addr & 0xffff, p); } @@ -3038,8 +3313,8 @@ s3_accel_read_w(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffe) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffe) { default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -3084,8 +3359,8 @@ s3_accel_read_l(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffffffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffc) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffc) { case 0x8180: temp = s3->streams.pri_ctrl; break; @@ -3241,6 +3516,7 @@ polygon_setup(s3_t *s3) } } + #define READ(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)]; @@ -3276,6 +3552,277 @@ polygon_setup(s3_t *s3) } + +#define ROPMIX_READ(D, P, S) \ + { \ + switch (rop) { \ + case 0x00: out = 0; break; \ + case 0x01: out = ~(D | (P | S)); break; \ + case 0x02: out = D & ~(P | S); break; \ + case 0x03: out = ~(P | S); break; \ + case 0x04: out = S & ~(D | P); break; \ + case 0x05: out = ~(D | P); break; \ + case 0x06: out = ~(P | ~(D ^ S)); break; \ + case 0x07: out = ~(P | (D & S)); break; \ + case 0x08: out = S & (D & ~P); break; \ + case 0x09: out = ~(P | (D ^ S)); break; \ + case 0x0a: out = D & ~P; break; \ + case 0x0b: out = ~(P | (S & ~D)); break; \ + case 0x0c: out = S & ~P; break; \ + case 0x0d: out = ~(P | (D & ~S)); break; \ + case 0x0e: out = ~(P | ~(D | S)); break; \ + case 0x0f: out = ~P; break; \ + case 0x10: out = P & ~(D | S); break; \ + case 0x11: out = ~(D | S); break; \ + case 0x12: out = ~(S | ~(D ^ P)); break; \ + case 0x13: out = ~(S | (D & P)); break; \ + case 0x14: out = ~(D | ~(P ^ S)); break; \ + case 0x15: out = ~(D | (P & S)); break; \ + case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ + case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ + case 0x18: out = (S ^ P) & (P ^ D); break; \ + case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ + case 0x1a: out = P ^ (D | (S & P)); break; \ + case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ + case 0x1c: out = P ^ (S | (D & P)); break; \ + case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ + case 0x1e: out = P ^ (D | S); break; \ + case 0x1f: out = ~(P & (D | S)); break; \ + case 0x20: out = D & (P & ~S); break; \ + case 0x21: out = ~(S | (D ^ P)); break; \ + case 0x22: out = D & ~S; break; \ + case 0x23: out = ~(S | (P & ~D)); break; \ + case 0x24: out = (S ^ P) & (D ^ S); break; \ + case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ + case 0x26: out = S ^ (D | (P & S)); break; \ + case 0x27: out = S ^ (D | ~(P ^ S)); break; \ + case 0x28: out = D & (P ^ S); break; \ + case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ + case 0x2a: out = D & ~(P & S); break; \ + case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ + case 0x2c: out = S ^ (P & (D | S)); break; \ + case 0x2d: out = P ^ (S | ~D); break; \ + case 0x2e: out = P ^ (S | (D ^ P)); break; \ + case 0x2f: out = ~(P & (S | ~D)); break; \ + case 0x30: out = P & ~S; break; \ + case 0x31: out = ~(S | (D & ~P)); break; \ + case 0x32: out = S ^ (D | (P | S)); break; \ + case 0x33: out = ~S; break; \ + case 0x34: out = S ^ (P | (D & S)); break; \ + case 0x35: out = S ^ (P | ~(D ^ S)); break; \ + case 0x36: out = S ^ (D | P); break; \ + case 0x37: out = ~(S & (D | P)); break; \ + case 0x38: out = P ^ (S & (D | P)); break; \ + case 0x39: out = S ^ (P | ~D); break; \ + case 0x3a: out = S ^ (P | (D ^ S)); break; \ + case 0x3b: out = ~(S & (P | ~D)); break; \ + case 0x3c: out = P ^ S; break; \ + case 0x3d: out = S ^ (P | ~(D | S)); break; \ + case 0x3e: out = S ^ (P | (D & ~S)); break; \ + case 0x3f: out = ~(P & S); break; \ + case 0x40: out = P & (S & ~D); break; \ + case 0x41: out = ~(D | (P ^ S)); break; \ + case 0x42: out = (S ^ D) & (P ^ D); break; \ + case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ + case 0x44: out = S & ~D; break; \ + case 0x45: out = ~(D | (P & ~S)); break; \ + case 0x46: out = D ^ (S | (P & D)); break; \ + case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ + case 0x48: out = S & (D ^ P); break; \ + case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ + case 0x4a: out = D ^ (P & (S | D)); break; \ + case 0x4b: out = P ^ (D | ~S); break; \ + case 0x4c: out = S & ~(D & P); break; \ + case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ + case 0x4e: out = P ^ (D | (S ^ P)); break; \ + case 0x4f: out = ~(P & (D | ~S)); break; \ + case 0x50: out = P & ~D; break; \ + case 0x51: out = ~(D | (S & ~P)); break; \ + case 0x52: out = D ^ (P | (S & D)); break; \ + case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ + case 0x54: out = ~(D | ~(P | S)); break; \ + case 0x55: out = ~D; break; \ + case 0x56: out = D ^ (P | S); break; \ + case 0x57: out = ~(D & (P | S)); break; \ + case 0x58: out = P ^ (D & (S | P)); break; \ + case 0x59: out = D ^ (P | ~S); break; \ + case 0x5a: out = D ^ P; break; \ + case 0x5b: out = D ^ (P | ~(S | D)); break; \ + case 0x5c: out = D ^ (P | (S ^ D)); break; \ + case 0x5d: out = ~(D & (P | ~S)); break; \ + case 0x5e: out = D ^ (P | (S & ~D)); break; \ + case 0x5f: out = ~(D & P); break; \ + case 0x60: out = P & (D ^ S); break; \ + case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ + case 0x62: out = D ^ (S & (P | D)); break; \ + case 0x63: out = S ^ (D | ~P); break; \ + case 0x64: out = S ^ (D & (P | S)); break; \ + case 0x65: out = D ^ (S | ~P); break; \ + case 0x66: out = D ^ S; break; \ + case 0x67: out = S ^ (D | ~(P | S)); break; \ + case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ + case 0x69: out = ~(P ^ (D ^ S)); break; \ + case 0x6a: out = D ^ (P & S); break; \ + case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ + case 0x6c: out = S ^ (D & P); break; \ + case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ + case 0x6e: out = S ^ (D & (P | ~S)); break; \ + case 0x6f: out = ~(P & ~(D ^ S)); break; \ + case 0x70: out = P & ~(D & S); break; \ + case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ + case 0x72: out = S ^ (D | (P ^ S)); break; \ + case 0x73: out = ~(S & (D | ~P)); break; \ + case 0x74: out = D ^ (S | (P ^ D)); break; \ + case 0x75: out = ~(D & (S | ~P)); break; \ + case 0x76: out = S ^ (D | (P & ~S)); break; \ + case 0x77: out = ~(D & S); break; \ + case 0x78: out = P ^ (D & S); break; \ + case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ + case 0x7a: out = D ^ (P & (S | ~D)); break; \ + case 0x7b: out = ~(S & ~(D ^ P)); break; \ + case 0x7c: out = S ^ (P & (D | ~S)); break; \ + case 0x7d: out = ~(D & ~(P ^ S)); break; \ + case 0x7e: out = (S ^ P) | (D ^ S); break; \ + case 0x7f: out = ~(D & (P & S)); break; \ + case 0x80: out = D & (P & S); break; \ + case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ + case 0x82: out = D & ~(P ^ S); break; \ + case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ + case 0x84: out = S & ~(D ^ P); break; \ + case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ + case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ + case 0x87: out = ~(P ^ (D & S)); break; \ + case 0x88: out = D & S; break; \ + case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ + case 0x8a: out = D & (S | ~P); break; \ + case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ + case 0x8c: out = S & (D | ~P); break; \ + case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ + case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ + case 0x8f: out = ~(P & ~(D & S)); break; \ + case 0x90: out = P & ~(D ^ S); break; \ + case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ + case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ + case 0x93: out = ~(S ^ (P & D)); break; \ + case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ + case 0x95: out = ~(D ^ (P & S)); break; \ + case 0x96: out = D ^ (P ^ S); break; \ + case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ + case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ + case 0x99: out = ~(D ^ S); break; \ + case 0x9a: out = D ^ (P & ~S); break; \ + case 0x9b: out = ~(S ^ (D & (P | S))); break; \ + case 0x9c: out = S ^ (P & ~D); break; \ + case 0x9d: out = ~(D ^ (S & (P | D))); break; \ + case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ + case 0x9f: out = ~(P & (D ^ S)); break; \ + case 0xa0: out = D & P; break; \ + case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ + case 0xa2: out = D & (P | ~S); break; \ + case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ + case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ + case 0xa5: out = ~(P ^ D); break; \ + case 0xa6: out = D ^ (S & ~P); break; \ + case 0xa7: out = ~(P ^ (D & (S | P))); break; \ + case 0xa8: out = D & (P | S); break; \ + case 0xa9: out = ~(D ^ (P | S)); break; \ + case 0xaa: out = D; break; \ + case 0xab: out = D | ~(P | S); break; \ + case 0xac: out = S ^ (P & (D ^ S)); break; \ + case 0xad: out = ~(D ^ (P | (S & D))); break; \ + case 0xae: out = D | (S & ~P); break; \ + case 0xaf: out = D | ~P; break; \ + case 0xb0: out = P & (D | ~S); break; \ + case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ + case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ + case 0xb3: out = ~(S & ~(D & P)); break; \ + case 0xb4: out = P ^ (S & ~D); break; \ + case 0xb5: out = ~(D ^ (P & (S | D))); break; \ + case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ + case 0xb7: out = ~(S & (D ^ P)); break; \ + case 0xb8: out = P ^ (S & (D ^ P)); break; \ + case 0xb9: out = ~(D ^ (S | (P & D))); break; \ + case 0xba: out = D | (P & ~S); break; \ + case 0xbb: out = D | ~S; break; \ + case 0xbc: out = S ^ (P & ~(D & S)); break; \ + case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ + case 0xbe: out = D | (P ^ S); break; \ + case 0xbf: out = D | ~(P & S); break; \ + case 0xc0: out = P & S; break; \ + case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ + case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ + case 0xc3: out = ~(P ^ S); break; \ + case 0xc4: out = S & (P | ~D); break; \ + case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ + case 0xc6: out = S ^ (D & ~P); break; \ + case 0xc7: out = ~(P ^ (S & (D | P))); break; \ + case 0xc8: out = S & (D | P); break; \ + case 0xc9: out = ~(S ^ (P | D)); break; \ + case 0xca: out = D ^ (P & (S ^ D)); break; \ + case 0xcb: out = ~(S ^ (P | (D & S))); break; \ + case 0xcc: out = S; break; \ + case 0xcd: out = S | ~(D | P); break; \ + case 0xce: out = S | (D & ~P); break; \ + case 0xcf: out = S | ~P; break; \ + case 0xd0: out = P & (S | ~D); break; \ + case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ + case 0xd2: out = P ^ (D & ~S); break; \ + case 0xd3: out = ~(S ^ (P & (D | S))); break; \ + case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ + case 0xd5: out = ~(D & ~(P & S)); break; \ + case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ + case 0xd7: out = ~(D & (P ^ S)); break; \ + case 0xd8: out = P ^ (D & (S ^ P)); break; \ + case 0xd9: out = ~(S ^ (D | (P & S))); break; \ + case 0xda: out = D ^ (P & ~(S & D)); break; \ + case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ + case 0xdc: out = S | (P & ~D); break; \ + case 0xdd: out = S | ~D; break; \ + case 0xde: out = S | (D ^ P); break; \ + case 0xdf: out = S | ~(D & P); break; \ + case 0xe0: out = P & (D | S); break; \ + case 0xe1: out = ~(P ^ (D | S)); break; \ + case 0xe2: out = D ^ (S & (P ^ D)); break; \ + case 0xe3: out = ~(P ^ (S | (D & P))); break; \ + case 0xe4: out = S ^ (D & (P ^ S)); break; \ + case 0xe5: out = ~(P ^ (D | (S & P))); break; \ + case 0xe6: out = S ^ (D & ~(P & S)); break; \ + case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ + case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ + case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ + case 0xea: out = D | (P & S); break; \ + case 0xeb: out = D | ~(P ^ S); break; \ + case 0xec: out = S | (D & P); break; \ + case 0xed: out = S | ~(D ^ P); break; \ + case 0xee: out = D | S; break; \ + case 0xef: out = S | (D | ~P); break; \ + case 0xf0: out = P; break; \ + case 0xf1: out = P | ~(D | S); break; \ + case 0xf2: out = P | (D & ~S); break; \ + case 0xf3: out = P | ~S; break; \ + case 0xf4: out = P | (S & ~D); break; \ + case 0xf5: out = P | ~D; break; \ + case 0xf6: out = P | (D ^ S); break; \ + case 0xf7: out = P | ~(D & S); break; \ + case 0xf8: out = P | (D & S); break; \ + case 0xf9: out = P | ~(D ^ S); break; \ + case 0xfa: out = D | P; break; \ + case 0xfb: out = D | (P | ~S); break; \ + case 0xfc: out = P | S; break; \ + case 0xfd: out = P | (S | ~D); break; \ + case 0xfe: out = D | (P | S); break; \ + case 0xff: out = ~0; break; \ + } \ + } + + +#define ROPMIX { \ + old_dest_dat = dest_dat; \ + ROPMIX_READ(dest_dat, pat_dat, src_dat); \ + out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } + + #define WRITE(addr, dat) if (s3->bpp == 0) \ { \ svga->vram[(addr) & s3->vram_mask] = dat; \ @@ -3298,6 +3845,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { svga_t *svga = &s3->svga; uint32_t src_dat = 0, dest_dat, old_dest_dat; + uint32_t out, pat_dat = 0; int frgd_mix, bkgd_mix; int clip_t = s3->accel.multifunc[1] & 0xfff; int clip_l = s3->accel.multifunc[2] & 0xfff; @@ -3308,6 +3856,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ uint16_t *vram_w = (uint16_t *)svga->vram; uint32_t *vram_l = (uint32_t *)svga->vram; uint32_t compare = s3->accel.color_cmp; + uint8_t rop = s3->accel.ropmix & 0xff; int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; @@ -3321,8 +3870,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((s3->chip >= S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968) && (s3->accel.cmd & (1 << 11))) { cmd |= 8; + } // SRC-BASE/DST-BASE if ((s3->accel.multifunc[0xd] >> 4) & 7) { @@ -3349,7 +3899,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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) { @@ -3377,7 +3927,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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 || s3->chip >= S3_TRIO64V) ? 0x80 : 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; @@ -3695,6 +4245,82 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } break; + + case 3: /*Polygon Fill Solid (Vision868/968 and Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + break; + + polygon_setup(s3); + + 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; + + 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 = dstbase + y * s3->width; + + while (x_count-- && count--) + { + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && + (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= 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; /*Not supported?*/ break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } + 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; + + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { @@ -3725,7 +4351,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7) { - while (1) + while (count-- && s3->accel.sy >= 0) { if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) @@ -3971,86 +4597,112 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } break; - - case 3: /*Polygon Fill Solid (Trio64 only)*/ - { - int end_y1, end_y2; + + case 9: /*Polyline/2-Point Line (Vision868/968 and Trio64 only)*/ + { + int error; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; - polygon_setup(s3); + if (!cpu_input) { + s3->accel.dx = ABS(s3->accel.destx_distp - s3->accel.cur_x); + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = ABS(s3->accel.desty_axstp - s3->accel.cur_y); + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~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; + } 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; - - 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 = dstbase + y * s3->width; - - while (x_count-- && count--) - { - if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && - (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) + if (s3->accel.dx > s3->accel.dy) { + error = s3->accel.dx / 2; + while (s3->accel.cx != s3->accel.destx_distp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= 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; /*Not supported?*/ break; - } + src_dat = s3->accel.frgd_color; if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.poly_x, dest_dat); - + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + MIX - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } - 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++; + error -= s3->accel.dy; + if (error < 0) { + error += s3->accel.dx; + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + } + + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; else - s3->accel.poly_x--; + s3->accel.cx--; } - - 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; + } else { + error = s3->accel.dy / 2; + while (s3->accel.cy != s3->accel.desty_axstp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) + { + src_dat = s3->accel.frgd_color; - case 11: /*Polygon Fill Pattern (Trio64 only)*/ + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + error -= s3->accel.dx; + if (error < 0) { + error += s3->accel.dy; + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; + else + s3->accel.cx--; + } + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + + } + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + + case 11: /*Polygon Fill Pattern (Vision868/968 and Trio64 only)*/ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; polygon_setup(s3); @@ -4133,6 +4785,144 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; } break; + + case 14: /*ROPBlt (Vision868/968 only)*/ + if (s3->chip != S3_VISION968) + break; + + 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.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.px = s3->accel.pat_x & 0xfff; + if (s3->accel.pat_x & 0x1000) s3->accel.px |= ~0xfff; + s3->accel.py = s3->accel.pat_y & 0xfff; + if (s3->accel.pat_y & 0x1000) s3->accel.py |= ~0xfff; + + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + } + + 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; + + while (count-- && s3->accel.sy >= 0) + { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= 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: READ(s3->accel.src + s3->accel.cx, src_dat); break; + } + + if (s3->accel.ropmix & 0x100) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.pat_bg_color; break; + case 1: pat_dat = s3->accel.pat_fg_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } else { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.bkgd_color; break; + case 1: pat_dat = s3->accel.frgd_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + ROPMIX + + WRITE(s3->accel.dest + s3->accel.dx, out); + } + } + + 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++; + s3->accel.px++; + } + else + { + s3->accel.cx--; + s3->accel.dx--; + s3->accel.px--; + } + 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; + s3->accel.px -= (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.px += (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++; + s3->accel.py++; + } + else + { + s3->accel.cy--; + s3->accel.dy--; + s3->accel.py--; + } + + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3->accel.sy--; + + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) { + return; + } + } + } + break; } } @@ -4150,7 +4940,11 @@ s3_pci_read(int func, int addr, void *p) case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; case PCI_REG_COMMAND: - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + if (s3->chip == S3_VISION968) + return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + else + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + break; case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -4158,13 +4952,13 @@ s3_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x00; /*Supports VGA interface*/ else return 0x01; break; case 0x0b: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x03; else return 0x00; @@ -4172,8 +4966,8 @@ s3_pci_read(int func, int addr, void *p) case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); - case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; + case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; @@ -4203,14 +4997,14 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x12: - if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2) { + if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968) { svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); } break; case 0x13: - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : val; + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968) ? (val & 0xfe) : val); s3_updatemapping(s3); break; @@ -4316,6 +5110,22 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; + case S3_ELSAWIN2KPROX_964: + bios_fn = ROM_ELSAWIN2KPROX_964; + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); + break; + case S3_ELSAWIN2KPROX: + bios_fn = ROM_ELSAWIN2KPROX; + chip = S3_VISION968; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + break; case S3_PHOENIX_TRIO32: bios_fn = ROM_PHOENIX_TRIO32; chip = S3_TRIO32; @@ -4432,7 +5242,7 @@ static void *s3_init(const device_t *info) mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - if (chip == S3_VISION964) + if (chip == S3_VISION964 || chip == S3_VISION968) svga_init(info, &s3->svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, @@ -4456,8 +5266,10 @@ static void *s3_init(const device_t *info) svga->hwcursor.ysize = 64; - if (chip == S3_VISION964) + if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || chip == S3_VISION968) + svga->dac_hwcursor_draw = ibm_rgb525_hwcursor_draw; if (chip >= S3_VISION964) { switch (vram) { @@ -4489,13 +5301,20 @@ static void *s3_init(const device_t *info) break; } } - - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + + if (chip == S3_VISION968) { + if (s3->pci) + svga->crtc[0x36] = 2 | (0 << 2) | (1 << 4); + else + svga->crtc[0x36] = 1 | (0 << 2) | (1 << 4); + } else { + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + } if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); @@ -4524,8 +5343,10 @@ static void *s3_init(const device_t *info) s3->fifo_thread = thread_create(fifo_thread, s3); s3->int_line = 0; + + s3->card_type = info->local; - switch(info->local) { + switch(s3->card_type) { case S3_ORCHID_86C911: case S3_DIAMOND_STEALTH_VRAM: svga->decode_mask = (1 << 20) - 1; @@ -4614,6 +5435,7 @@ static void *s3_init(const device_t *info) break; case S3_DIAMOND_STEALTH64_964: + case S3_ELSAWIN2KPROX_964: svga->decode_mask = (8 << 20) - 1; stepping = 0xd0; /*Vision964*/ s3->id = stepping; @@ -4621,10 +5443,33 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&bt485_ramdac_device); + svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb525_ramdac_device) : device_add(&bt485_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - break; + break; + + case S3_ELSAWIN2KPROX: + svga->decode_mask = (8 << 20) - 1; + s3->id = 0xe1; /*Vision968*/ + s3->id_ext = 0xb0; + s3->id_ext_pci = 0xf0; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + svga->ramdac = device_add(&ibm_rgb525_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; case S3_PHOENIX_TRIO32: case S3_DIAMOND_STEALTH_SE: @@ -4723,6 +5568,16 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } +static int s3_elsa_winner2000_pro_x_964_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX_964); +} + +static int s3_elsa_winner2000_pro_x_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX); +} + static int s3_phoenix_trio32_available(void) { return rom_present(ROM_PHOENIX_TRIO32); @@ -4855,7 +5710,7 @@ static const device_config_t s3_phoenix_trio32_config[] = } }; -static const device_config_t s3_phoenix_trio64_onboard_config[] = +static const device_config_t s3_standard_config[] = { { "memory", "Video memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4879,7 +5734,7 @@ static const device_config_t s3_phoenix_trio64_onboard_config[] = } }; -static const device_config_t s3_config[] = +static const device_config_t s3_968_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4987,7 +5842,7 @@ const device_t s3_metheus_86c928_isa_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_vlb_device = @@ -5001,7 +5856,7 @@ const device_t s3_metheus_86c928_vlb_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_pci_device = @@ -5015,7 +5870,7 @@ const device_t s3_metheus_86c928_pci_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_bahamas64_vlb_device = @@ -5057,7 +5912,7 @@ const device_t s3_diamond_stealth64_964_vlb_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_964_pci_device = @@ -5071,7 +5926,7 @@ const device_t s3_diamond_stealth64_964_pci_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_9fx_vlb_device = @@ -5170,7 +6025,7 @@ const device_t s3_phoenix_trio64_vlb_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64_onboard_pci_device = @@ -5184,7 +6039,7 @@ const device_t s3_phoenix_trio64_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64_pci_device = @@ -5198,7 +6053,7 @@ const device_t s3_phoenix_trio64_pci_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_vlb_device = @@ -5212,7 +6067,7 @@ const device_t s3_phoenix_trio64vplus_vlb_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_onboard_pci_device = @@ -5226,7 +6081,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_pci_device = @@ -5240,7 +6095,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_vlb_device = @@ -5254,7 +6109,7 @@ const device_t s3_phoenix_vision864_vlb_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_pci_device = @@ -5268,7 +6123,7 @@ const device_t s3_phoenix_vision864_pci_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_vlb_device = @@ -5299,6 +6154,63 @@ const device_t s3_diamond_stealth64_pci_device = s3_9fx_config }; +const device_t s3_elsa_winner2000_pro_x_964_pci_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_964_vlb_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_pci_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_vlb_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + + const device_t s3_trio64v2_dx_pci_device = { "S3 Trio64V2/DX PCI", @@ -5310,5 +6222,6 @@ const device_t s3_trio64v2_dx_pci_device = { s3_trio64v2_dx_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; + diff --git a/src/video/vid_table.c b/src/video/vid_table.c index c29afba8a..0a6c6c17c 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -128,6 +128,8 @@ video_cards[] = { { "stealth3d_3000_pci", &s3_virge_988_pci_device }, { "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) { "mystique", &mystique_device }, @@ -164,6 +166,8 @@ video_cards[] = { { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "elsawin2kprox_964_vlb", &s3_elsa_winner2000_pro_x_964_vlb_device }, + { "elsawin2kprox_vlb", &s3_elsa_winner2000_pro_x_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "n9_9fx_vlb", &s3_9fx_vlb_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 16dc134bf..6df04bacd 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -752,7 +752,7 @@ VIDOBJ := video.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ vid_s3.o vid_s3_virge.o \ - vid_sdac_ramdac.o \ + vid_ibm_rgb525_ramdac.o vid_sdac_ramdac.o \ vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o \ From 9935faef37203cf6e978d8a09d7163fc5d5ffb9b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Dec 2020 13:23:37 +0100 Subject: [PATCH 02/60] Fixed the new MMIO mapping size of the S3 Virge968, Paintbrush no longer hangs but does not display correctly, pending the implementation of the Video engine. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index dafd25ebc..8e2523bbb 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2709,7 +2709,7 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); + mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { pclog("New MMIO disabled\n", s3->linear_base); mem_mapping_disable(&s3->new_mmio_mapping); From 27b6940dc86b2be45dd0033353107afbea708ec0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 15 Dec 2020 19:51:48 +0100 Subject: [PATCH 03/60] Fixed S3 linear mapping on Vision964 and earlier. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8e2523bbb..7f310a2d1 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2679,7 +2679,7 @@ s3_updatemapping(s3_t *s3) } else { if (s3->chip >= S3_TRIO64V) s3->linear_base &= 0xfc000000; - else + else if (s3->chip == S3_VISION968) s3->linear_base &= 0xfe000000; pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); From 3f45852af7ea3fe08120bb371d4cba8efdd77da1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 18 Dec 2020 22:40:51 +0100 Subject: [PATCH 04/60] Fixed arrow keys on Tandy machines. --- src/device/keyboard_xt.c | 5 +++++ src/machine/m_tandy.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 9a234b6eb..ce920f10a 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -425,6 +425,11 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) if (!adddata) return; + if (is_t1x00) { + adddata(val); + return; + } + keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 470cd099c..fbfb6054d 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -298,11 +298,11 @@ static const scancode scancode_tandy[512] = { { {0}, {0} }, { {0}, {0} }, /*140*/ { {0}, {0} }, { {0}, {0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ - { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, + { {0x29, 0}, {0xa9, 0} }, { {0x49, 0}, {0xc9, 0} }, + { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*148*/ + { {0}, {0} }, { {0x4e, 0}, {0xce, 0} }, { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, + { {0x4a, 0}, {0xca, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*154*/ From c881dc975fbd16066fdab91aee69cb0ab67f28df Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 18 Dec 2020 22:58:57 +0100 Subject: [PATCH 05/60] Fixed a segmentation fault when hard resetting on some Amstrads. --- src/machine/m_amstrad.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index ec0bff6ec..21d1d8805 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -1715,8 +1715,13 @@ vid_close_200(void *priv) { amsvid_t *vid = (amsvid_t *)priv; - free(vid->cga.vram); - free(vid->mda.vram); + if (vid->cga.vram != vid->mda.vram) { + free(vid->cga.vram); + free(vid->mda.vram); + } else + free(vid->cga.vram); + + vid->cga.vram = vid->mda.vram = NULL; free(vid); } From dd125854f16f1d161b6d050fd87e3469cfd18374 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 19 Dec 2020 00:04:36 +0100 Subject: [PATCH 06/60] Fixed warnings when compiling without the keyboard hook. --- src/win/win_ui.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 7d9c88164..0cc399117 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -70,8 +70,11 @@ extern WCHAR wopenfilestring[512]; /* Local data. */ static wchar_t wTitle[512]; +#ifndef NO_KEYBOARD_HOOK static HHOOK hKeyboardHook; -static int hook_enabled = 0, manager_wm = 0; +static int hook_enabled = 0; +#endif +static int manager_wm = 0; static int save_window_pos = 0, pause_state = 0; static int dpi = 96; static int padded_frame = 0; @@ -295,6 +298,7 @@ ResetAllMenus(void) } +#ifndef NO_KEYBOARD_HOOK static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { @@ -326,6 +330,7 @@ LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); } +#endif void @@ -360,7 +365,9 @@ plat_power_off(void) run before the main thread is terminated */ cycles -= 99999999; +#ifndef NO_KEYBOARD_HOOK UnhookWindowsHookEx(hKeyboardHook); +#endif KillTimer(hwndMain, TIMER_1SEC); PostQuitMessage(0); From bc12981935dd506d557ec9c8654f2d86c6d10866 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 19 Dec 2020 00:06:41 +0100 Subject: [PATCH 07/60] Fixed arrow keys on the Amstrads and indentation of the Olivetti machine code. --- src/device/keyboard_xt.c | 32 ++-- src/include/86box/keyboard.h | 1 + src/machine/m_amstrad.c | 4 +- src/machine/m_xt_olivetti.c | 287 +++++++++++++++++++---------------- 4 files changed, 177 insertions(+), 147 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index ce920f10a..7af93103d 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -330,7 +330,8 @@ const scancode scancode_xt[512] = { static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; -static int is_t1x00 = 0; +static int is_tandy = 0, is_t1x00 = 0, + is_amstrad = 0; #ifdef ENABLE_KEYBOARD_XT_LOG @@ -425,7 +426,7 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) if (!adddata) return; - if (is_t1x00) { + if (is_tandy) { adddata(val); return; } @@ -433,6 +434,9 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) keyboard_get_states(NULL, &num_lock, NULL); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; + if (is_amstrad) + num_lock = !num_lock; + switch(val) { case FAKE_LSHIFT_ON: if (num_lock) { @@ -558,15 +562,13 @@ kbd_read(uint16_t port, void *priv) ret = ((mem_size-64) / 32) & 0x0f; else ret = ((mem_size-64) / 32) >> 4; - } - else if (kbd->type == 8) { - /* Olivetti M19 */ - if (kbd->pb & 0x04) + } else if (kbd->type == 8) { + /* Olivetti M19 */ + if (kbd->pb & 0x04) ret = kbd->pd; - else - ret = kbd->pd >> 4; - } - else { + else + ret = kbd->pd >> 4; + } else { if (kbd->pb & 0x08) ret = kbd->pd >> 4; else { @@ -618,6 +620,13 @@ kbd_reset(void *priv) } +void +keyboard_set_is_amstrad(int ams) +{ + is_amstrad = ams; +} + + static void * kbd_init(const device_t *info) { @@ -732,8 +741,11 @@ kbd_init(const device_t *info) keyboard_set_table(scancode_xt); + is_tandy = (kbd->type == 5); is_t1x00 = (kbd->type == 6); + is_amstrad = 0; + return(kbd); } diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 3785a8f6d..fe0593b19 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -102,6 +102,7 @@ extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); extern int keyboard_recv(uint16_t key); extern int keyboard_isfsexit(void); extern int keyboard_ismsexit(void); +extern void keyboard_set_is_amstrad(int ams); extern void keyboard_at_adddata_keyboard_raw(uint8_t val); extern void keyboard_at_adddata_mouse(uint8_t val); diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 21d1d8805..44904c0c8 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2116,8 +2116,7 @@ kbd_adddata(uint16_t val) static void kbd_adddata_ex(uint16_t val) { - kbd_adddata(val); - // kbd_adddata_process(val, kbd_adddata); + kbd_adddata_process(val, kbd_adddata); } @@ -2500,6 +2499,7 @@ machine_amstrad_init(const machine_t *model, int type) keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; keyboard_scan = 1; + keyboard_set_is_amstrad(1); io_sethandler(0x0078, 2, ms_read, NULL, NULL, ms_write, NULL, NULL, ams); diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index a52588ce0..a2f3d2725 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -118,6 +118,7 @@ m24_log(const char *fmt, ...) #define m24_log(fmt, ...) #endif + static void m24_kbd_poll(void *priv) { @@ -171,9 +172,8 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) #endif #if 0 - if (ram[8] == 0xc3) { + if (ram[8] == 0xc3) output = 3; - } #endif switch (port) { case 0x60: @@ -242,6 +242,7 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) } } + static uint8_t m24_kbd_read(uint16_t port, void *priv) { @@ -279,11 +280,13 @@ m24_kbd_read(uint16_t port, void *priv) return(ret); } + static void m24_kbd_close(void *priv) { - olim24_kbd_t *kbd = (olim24_kbd_t *)priv; - /* Stop the timer. */ + olim24_kbd_t *kbd = (olim24_kbd_t *)priv; + + /* Stop the timer. */ timer_disable(&kbd->send_delay_timer); /* Disable scanning. */ @@ -293,12 +296,13 @@ m24_kbd_close(void *priv) io_removehandler(0x0060, 2, m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); - io_removehandler(0x0064, 1, + io_removehandler(0x0064, 1, m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); free(kbd); } + static void m24_kbd_reset(void *priv) { @@ -319,6 +323,7 @@ m24_kbd_reset(void *priv) m24_kbd->scan[6] = 0x50; } + static int ms_poll(int x, int y, int z, int b, void *priv) { @@ -401,10 +406,12 @@ ms_poll(int x, int y, int z, int b, void *priv) return(0); } + static void -m24_kbd_init(olim24_kbd_t *kbd){ +m24_kbd_init(olim24_kbd_t *kbd) +{ - /* Initialize the keyboard. */ + /* Initialize the keyboard. */ io_sethandler(0x0060, 2, m24_kbd_read, NULL, NULL, m24_kbd_write, NULL, NULL, kbd); io_sethandler(0x0064, 1, @@ -418,152 +425,160 @@ m24_kbd_init(olim24_kbd_t *kbd){ mouse_set_poll(ms_poll, kbd); keyboard_set_table(scancode_xt); - + keyboard_set_is_amstrad(0); } + static void m19_vid_out(uint16_t addr, uint8_t val, void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - int oldmode = vid->mode; - - /* activating plantronics mode */ - if (addr == 0x3dd){ - /* already in graphics mode */ - if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2)) { - vid->mode = PLANTRONICS_MODE; - } else { - vid->mode = OLIVETTI_OGC_MODE; -} - /* setting graphics mode */ - } else if (addr == 0x3d8) { - if ((val & 0x2) && (vid->colorplus.control & 0x30)){ - vid->mode = PLANTRONICS_MODE; - } else { - vid->mode = OLIVETTI_OGC_MODE; - } + olim19_vid_t *vid = (olim19_vid_t *)priv; + int oldmode = vid->mode; + + /* activating plantronics mode */ + if (addr == 0x3dd) { + /* already in graphics mode */ + if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2)) + vid->mode = PLANTRONICS_MODE; + else + vid->mode = OLIVETTI_OGC_MODE; + /* setting graphics mode */ + } else if (addr == 0x3d8) { + if ((val & 0x2) && (vid->colorplus.control & 0x30)) + vid->mode = PLANTRONICS_MODE; + else + vid->mode = OLIVETTI_OGC_MODE; + } + /* video mode changed */ + if (oldmode != vid->mode) { + /* activate Plantronics emulation */ + if (vid->mode == PLANTRONICS_MODE){ + timer_disable(&vid->ogc.cga.timer); + timer_set_delay_u64(&vid->colorplus.cga.timer, 0); + /* return to OGC mode */ + } else { + timer_disable(&vid->colorplus.cga.timer); + timer_set_delay_u64(&vid->ogc.cga.timer, 0); } - /* video mode changed */ - if(oldmode != vid->mode){ - /* activate Plantronics emulation */ - if (vid->mode == PLANTRONICS_MODE){ - timer_disable(&vid->ogc.cga.timer); - timer_set_delay_u64(&vid->colorplus.cga.timer, 0); - /* return to OGC mode */ - } else { - timer_disable(&vid->colorplus.cga.timer); - timer_set_delay_u64(&vid->ogc.cga.timer, 0); - } - colorplus_recalctimings(&vid->colorplus); - ogc_recalctimings(&vid->ogc); - } - colorplus_out(addr, val, &vid->colorplus); - ogc_out(addr, val, &vid->ogc); + + colorplus_recalctimings(&vid->colorplus); + ogc_recalctimings(&vid->ogc); + } + + colorplus_out(addr, val, &vid->colorplus); + ogc_out(addr, val, &vid->ogc); } + static uint8_t m19_vid_in(uint16_t addr, void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - if ( vid->mode == PLANTRONICS_MODE ) { - return colorplus_in(addr, &vid->colorplus); - } else { - return ogc_in(addr, &vid->ogc); + olim19_vid_t *vid = (olim19_vid_t *)priv; + + if (vid->mode == PLANTRONICS_MODE) + return colorplus_in(addr, &vid->colorplus); + else + return ogc_in(addr, &vid->ogc); } -} static uint8_t m19_vid_read(uint32_t addr, void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - vid->colorplus.cga.mapping = vid->ogc.cga.mapping; - if ( vid->mode == PLANTRONICS_MODE ) { - return colorplus_read(addr, &vid->colorplus); - } else { - return ogc_read(addr, &vid->ogc); -} + olim19_vid_t *vid = (olim19_vid_t *)priv; + + vid->colorplus.cga.mapping = vid->ogc.cga.mapping; + if (vid->mode == PLANTRONICS_MODE) + return colorplus_read(addr, &vid->colorplus); + else + return ogc_read(addr, &vid->ogc); } + static void m19_vid_write(uint32_t addr, uint8_t val, void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - colorplus_write(addr, val, &vid->colorplus); - ogc_write(addr, val, &vid->ogc); + olim19_vid_t *vid = (olim19_vid_t *)priv; + + colorplus_write(addr, val, &vid->colorplus); + ogc_write(addr, val, &vid->ogc); } static void m19_vid_close(void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - free(vid->ogc.cga.vram); + olim19_vid_t *vid = (olim19_vid_t *)priv; + + free(vid->ogc.cga.vram); free(vid->colorplus.cga.vram); - free(vid); + free(vid); } + static void m19_vid_speed_changed(void *priv) { - olim19_vid_t *vid = (olim19_vid_t *)priv; - colorplus_recalctimings(&vid->colorplus); - ogc_recalctimings(&vid->ogc); + olim19_vid_t *vid = (olim19_vid_t *)priv; + + colorplus_recalctimings(&vid->colorplus); + ogc_recalctimings(&vid->ogc); } + static void -m19_vid_init(olim19_vid_t *vid){ +m19_vid_init(olim19_vid_t *vid) +{ + /* int display_type; */ + vid->mode = OLIVETTI_OGC_MODE; - //int display_type; - vid->mode = OLIVETTI_OGC_MODE; + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_m19_vid); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_m19_vid); + /* display_type = device_get_config_int("display_type"); */ - //display_type = device_get_config_int("display_type"); - - /* OGC emulation part begin */ - loadfont_ex(L"roms/machines/olivetti_m19/BIOS.BIN", 1, 90); - /* composite is not working yet */ - vid->ogc.cga.composite = 0; // (display_type != CGA_RGB); - //vid->ogc.cga.snow_enabled = device_get_config_int("snow_enabled"); - - vid->ogc.cga.vram = malloc(0x8000); + /* OGC emulation part begin */ + loadfont_ex(L"roms/machines/olivetti_m19/BIOS.BIN", 1, 90); + /* composite is not working yet */ + vid->ogc.cga.composite = 0; // (display_type != CGA_RGB); + /* vid->ogc.cga.snow_enabled = device_get_config_int("snow_enabled"); */ - //cga_comp_init(vid->ogc.cga.revision); - - //vid->ogc.cga.rgb_type = device_get_config_int("rgb_type"); - //cga_palette = (vid->ogc.cga.rgb_type << 1); + vid->ogc.cga.vram = malloc(0x8000); + + /* cga_comp_init(vid->ogc.cga.revision); */ + + /* vid->ogc.cga.rgb_type = device_get_config_int("rgb_type"); */ + /* cga_palette = (vid->ogc.cga.rgb_type << 1); */ cga_palette = 0; - cgapal_rebuild(); - ogc_mdaattr_rebuild(); + cgapal_rebuild(); + ogc_mdaattr_rebuild(); - /* color display */ - // if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) - vid->ogc.mono_display = 1; - // else - // vid->ogc.mono_display = 1; - /* OGC emulation part end */ - - /* Plantronics emulation part begin*/ - /* composite is not working yet */ - vid->colorplus.cga.composite = 0; //(display_type != CGA_RGB); - // vid->colorplus.cga.snow_enabled = device_get_config_int("snow_enabled"); + /* color display */ + /* if (device_get_config_int("rgb_type")==0 || device_get_config_int("rgb_type") == 4) */ + vid->ogc.mono_display = 1; + /* else */ + /* vid->ogc.mono_display = 1; */ + /* OGC emulation part end */ + + /* Plantronics emulation part begin*/ + /* composite is not working yet */ + vid->colorplus.cga.composite = 0; //(display_type != CGA_RGB); + /* vid->colorplus.cga.snow_enabled = device_get_config_int("snow_enabled"); */ vid->colorplus.cga.vram = malloc(0x8000); - - //vid->colorplus.cga.cgamode = 0x1; - /* Plantronics emulation part end*/ - timer_add(&vid->ogc.cga.timer, ogc_poll, &vid->ogc, 1); - timer_add(&vid->colorplus.cga.timer, colorplus_poll, &vid->colorplus, 1); - timer_disable(&vid->colorplus.cga.timer); - mem_mapping_add(&vid->ogc.cga.mapping, 0xb8000, 0x08000, m19_vid_read, NULL, NULL, m19_vid_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, vid); - io_sethandler(0x03d0, 0x0010, m19_vid_in, NULL, NULL, m19_vid_out, NULL, NULL, vid); - - vid->mode = OLIVETTI_OGC_MODE; - + /* vid->colorplus.cga.cgamode = 0x1; */ + /* Plantronics emulation part end*/ + + timer_add(&vid->ogc.cga.timer, ogc_poll, &vid->ogc, 1); + timer_add(&vid->colorplus.cga.timer, colorplus_poll, &vid->colorplus, 1); + timer_disable(&vid->colorplus.cga.timer); + mem_mapping_add(&vid->ogc.cga.mapping, 0xb8000, 0x08000, m19_vid_read, NULL, NULL, m19_vid_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, vid); + io_sethandler(0x03d0, 0x0010, m19_vid_in, NULL, NULL, m19_vid_out, NULL, NULL, vid); + + vid->mode = OLIVETTI_OGC_MODE; } + const device_t m24_kbd_device = { "Olivetti M24 keyboard and mouse", 0, @@ -590,11 +605,13 @@ m19_get_device(void) return &m19_vid_device; } + static uint8_t m24_read(uint16_t port, void *priv) { - uint8_t ret = 0x00; - int i, fdd_count = 0; + uint8_t ret = 0x00; + int i, fdd_count = 0; + switch (port) { /* * port 66: @@ -610,7 +627,7 @@ m24_read(uint16_t port, void *priv) /* Switch 5 - 8087 present */ if (hasfpu) ret |= 0x10; - /* + /* * Switches 1, 2, 3, 4 - installed memory * Switch 8 - Use memory bank 1 */ @@ -650,10 +667,9 @@ m24_read(uint16_t port, void *priv) */ case 0x67: for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) { + if (fdd_get_flags(i)) fdd_count++; } - } /* Switches 7, 8 - floppy drives. */ if (!fdd_count) @@ -674,17 +690,19 @@ m24_read(uint16_t port, void *priv) /* Switch 2 - Set fast startup */ ret |= 0x2; -} + } return(ret); } + const device_t * m24_get_device(void) { return &ogc_m24_device; } + int machine_xt_olim24_init(const machine_t *model) { @@ -708,22 +726,21 @@ machine_xt_olim24_init(const machine_t *model) machine_common_init(model); device_add(&fdc_xt_device); - //address 66-67 = mainboard dip-switch settings - io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); + /* Address 66-67 = mainboard dip-switch settings */ + io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); - m24_kbd_init(m24_kbd); - device_add_ex(&m24_kbd_device, m24_kbd); + m24_kbd_init(m24_kbd); + device_add_ex(&m24_kbd_device, m24_kbd); - /* FIXME: make sure this is correct?? */ + /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); if (joystick_type) - device_add(&gameport_device); + device_add(&gameport_device); nmi_init(); - - return ret; + return ret; } /* @@ -746,10 +763,10 @@ machine_xt_olim240_init(const machine_t *model) pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - /* - * port 60: should return jumper settings only under unknown conditions - * SWB on mainboard (off=1) - * bit 7 - use BIOS HD on mainboard (on) / on controller (off) + /* + * port 60: should return jumper settings only under unknown conditions + * SWB on mainboard (off=1) + * bit 7 - use BIOS HD on mainboard (on) / on controller (off) * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) */ device_add(&keyboard_at_olivetti_device); @@ -757,11 +774,11 @@ machine_xt_olim240_init(const machine_t *model) /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); - if (joystick_type) - device_add(&gameport_device); + if (joystick_type) + device_add(&gameport_device); nmi_init(); @@ -787,19 +804,19 @@ machine_xt_olim19_init(const machine_t *model) olim19_vid_t *vid; - /* do not move memory allocation elsewhere */ - vid = (olim19_vid_t *)malloc(sizeof(olim19_vid_t)); - memset(vid, 0x00, sizeof(olim19_vid_t)); + /* Do not move memory allocation elsewhere. */ + vid = (olim19_vid_t *)malloc(sizeof(olim19_vid_t)); + memset(vid, 0x00, sizeof(olim19_vid_t)); machine_common_init(model); device_add(&fdc_xt_device); - m19_vid_init(vid); - device_add_ex(&m19_vid_device, vid); + m19_vid_init(vid); + device_add_ex(&m19_vid_device, vid); - device_add(&keyboard_xt_olivetti_device); - - nmi_init(); + device_add(&keyboard_xt_olivetti_device); + + nmi_init(); return ret; From 643f9b46ea5ba2e3f2ff6d183de6e5188d262829 Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Sat, 19 Dec 2020 12:16:42 +0100 Subject: [PATCH 08/60] Added the following new machines: - Zenith Data Systems Z-151/152/161 - Zenith Data Systems Z-159 - Columbia Data Products MPC-1600 - Eagle PC Spirit Minor tweaks and renamings --- src/device/keyboard_xt.c | 145 +++++++++++++++++++++++++++-------- src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 14 +++- src/machine/m_xt.c | 45 ++++++++++- src/machine/m_xt_zenith.c | 91 +++++++++++++++++++--- src/machine/machine_table.c | 6 +- 6 files changed, 255 insertions(+), 47 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 9a234b6eb..9c8a9351b 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -352,6 +352,34 @@ kbd_log(const char *fmt, ...) #define kbd_log(fmt, ...) #endif +static uint8_t +get_fdd_switch_settings(){ + + int i, fdd_count = 0; + + for (i = 0; i < FDD_NUM; i++) { + if (fdd_get_flags(i)) + fdd_count++; + } + + if (!fdd_count) + return 0x00; + else + return ((fdd_count - 1) << 6) | 0x01; + +} + +static uint8_t +get_videomode_switch_settings(){ + + if (video_is_mda()) + return 0x30; + else if (video_is_cga()) + return 0x20; /* 0x10 would be 40x25 */ + else + return 0x00; + +} static void kbd_poll(void *priv) @@ -530,6 +558,7 @@ kbd_read(uint16_t port, void *priv) { xtkbd_t *kbd = (xtkbd_t *)priv; uint8_t ret = 0xff; + switch (port) { case 0x60: @@ -537,9 +566,28 @@ kbd_read(uint16_t port, void *priv) ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); else if (((kbd->type == 2) || (kbd->type == 3)) && (kbd->pb & 0x80)) ret = 0xff; /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ - else - ret = kbd->pa; - break; + else if ((kbd->type == 9) && (kbd->pb & 0x80)) { + /* Zenith Data Systems Z-151 + * SW1 switch settings: + * bits 6-7: floppy drive number + * bits 4-5: video mode + * bit 2-3: base memory size + * bit 1: fpu enable + * bit 0: fdc enable + */ + ret = get_fdd_switch_settings(); + + ret |= get_videomode_switch_settings(); + + /* base memory size should always be 64k */ + ret |= 0x0c; + + if (hasfpu) + ret |= 0x02; + + } else + ret = kbd->pa; + break; case 0x61: ret = kbd->pb; @@ -548,18 +596,20 @@ kbd_read(uint16_t port, void *priv) case 0x62: if (kbd->type == 0) ret = 0x00; - else if (kbd->type == 1) { + else if (kbd->type == 1) { if (kbd->pb & 0x04) ret = ((mem_size-64) / 32) & 0x0f; else ret = ((mem_size-64) / 32) >> 4; } - else if (kbd->type == 8) { - /* Olivetti M19 */ + else if (kbd->type == 8 || kbd->type == 9) { + /* Olivetti M19 or Zenith Data Systems Z-151*/ if (kbd->pb & 0x04) - ret = kbd->pd; + ret = kbd->pd & 0xbf; + //return 0x00; else ret = kbd->pd >> 4; + //return 0x00; } else { if (kbd->pb & 0x08) @@ -589,6 +639,7 @@ kbd_read(uint16_t port, void *priv) case 0x63: if ((kbd->type == 2) || (kbd->type == 3) || (kbd->type == 4) || (kbd->type == 6)) ret = kbd->pd; + break; } @@ -616,8 +667,6 @@ kbd_reset(void *priv) static void * kbd_init(const device_t *info) { - int i, fdd_count = 0; - xtkbd_t *kbd; kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t)); @@ -634,33 +683,21 @@ kbd_init(const device_t *info) video_reset(gfxcard); if (kbd->type <= 3 || kbd-> type == 8) { - for (i = 0; i < FDD_NUM; i++) { - if (fdd_get_flags(i)) - fdd_count++; - } - + /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type != 8) /* Switches 7, 8 - floppy drives. */ - if (!fdd_count) - kbd->pd = 0x00; - else - kbd->pd = ((fdd_count - 1) << 6) | 0x01; + kbd->pd = get_fdd_switch_settings(); else - /* Jumpers J1, J2 - monitor type. - * 01 - mono (high-res) - * 10 - color (low-res, disables 640x400x2 mode) - * 00 - autoswitching - */ + /* Olivetti M19 + * Jumpers J1, J2 - monitor type. + * 01 - mono (high-res) + * 10 - color (low-res, disables 640x400x2 mode) + * 00 - autoswitching + */ kbd->pd |= 0x00; - /* Switches 5, 6 - video. */ - if (video_is_mda()) - kbd->pd |= 0x30; - else if (video_is_cga()) - kbd->pd |= 0x20; /* 0x10 would be 40x25 */ - else - kbd->pd |= 0x00; + kbd->pd |= get_videomode_switch_settings(); /* Switches 3, 4 - memory size. */ // Note to Compaq/Toshiba keyboard maintainers: type 4 and 6 will never be activated in this block @@ -721,6 +758,44 @@ kbd_init(const device_t *info) /* Switch 1 - always off. */ kbd->pd |= 0x01; + } else if (kbd-> type == 9) { + /* Zenith Data Systems Z-151 + * SW2 switch settings: + * bit 7: monitor frequency + * bits 5-6: autoboot (00-11 resident monitor, 10 hdd, 01 fdd) + * bits 0-4: installed memory + */ + kbd->pd = 0x20; + switch (mem_size) { + case 128: + kbd->pd |= 0x02; + break; + case 192: + kbd->pd |= 0x04; + break; + case 256: + kbd->pd |= 0x02|0x04; + break; + case 320: + kbd->pd |= 0x08; + break; + case 384: + kbd->pd |= 0x02|0x08; + break; + case 448: + kbd->pd |= 0x04|0x08; + break; + case 512: + kbd->pd |= 0x02|0x04|0x08; + break; + case 576: + kbd->pd |= 0x10; + break; + case 640: + default: + kbd->pd |= 0x02|0x10; + break; + } } timer_add(&kbd->send_delay_timer, kbd_poll, kbd, 1); @@ -844,3 +919,13 @@ const device_t keyboard_xt_olivetti_device = { kbd_reset, { NULL }, NULL, NULL }; + +const device_t keyboard_xt_zenith_device = { + "Zenith XT Keyboard", + 0, + 9, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL +}; diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 3785a8f6d..126e50afc 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -69,6 +69,7 @@ extern const device_t keyboard_tandy_device; extern const device_t keyboard_xt_lxt3_device; #endif extern const device_t keyboard_xt_olivetti_device; +extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; extern const device_t keyboard_at_toshiba_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d920ef494..25811a9c6 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -511,10 +511,13 @@ extern const device_t europc_device; /* m_xt_olivetti.c */ extern int machine_xt_olim24_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t *m24_get_device(void); +#endif extern int machine_xt_olim240_init(const machine_t *); extern int machine_xt_olim19_init(const machine_t *); #ifdef EMU_DEVICE_H -extern const device_t *m24_get_device(void); +extern const device_t *m19_get_device(void); #endif /* m_pcjr.c */ @@ -579,6 +582,8 @@ extern int machine_xt_jukopc_init(const machine_t *); extern int machine_xt_open_xt_init(const machine_t *); extern int machine_xt_pxxt_init(const machine_t *); extern int machine_xt_ncrpc4i_init(const machine_t *); +extern int machine_xt_mpc1600_init(const machine_t *); +extern int machine_xt_eaglepcspirit_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); @@ -606,7 +611,12 @@ extern const device_t *t1200_get_device(void); #endif /* m_xt_zenith.c */ -extern int machine_xt_zenith_init(const machine_t *); +extern int machine_xt_z184_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t *z184_get_device(void); +#endif +extern int machine_xt_z151_init(const machine_t *); +extern int machine_xt_z159_init(const machine_t *); /* m_xt_xi8088.c */ extern int machine_xt_xi8088_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index e94c7bc28..c5c1acc1c 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -26,11 +26,11 @@ machine_xt_common_init(const machine_t *model) pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + device_add(&fdc_xt_device); nmi_init(); if (joystick_type) - device_add(&gameport_device); + device_add(&gameport_device); } @@ -332,12 +332,51 @@ machine_xt_ncrpc4i_init(const machine_t *model) 0x000fc000, 16384, 0); if (bios_only || !ret) - return ret; + return ret; machine_xt_clone_init(model); return ret; } +int +machine_xt_mpc1600_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/mpc1600/mpc4.34_merged.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc82_device); + + machine_xt_common_init(model); + + return ret; +} +int +machine_xt_eaglepcspirit_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/eagle_pcspirit/u1101.bin", + 0x000fe000, 16384, 0); + + if (ret) { + bios_load_aux_linear(L"roms/machines/eagle_pcspirit/u1103.bin", + 0x000fc000, 8192, 0); + } + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc82_device); + + machine_xt_common_init(model); + + return ret; +} \ No newline at end of file diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 7b7ea2409..6e5ac1729 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -42,6 +42,8 @@ #include <86box/lpt.h> #include <86box/serial.h> #include <86box/machine.h> +#include <86box/io.h> +#include <86box/vid_cga.h> typedef struct { @@ -105,8 +107,36 @@ static const device_t zenith_scratchpad_device = { }; +void +machine_zenith_init(const machine_t *model){ + + machine_common_init(model); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + device_add(&zenith_scratchpad_device); + + pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + + device_add(&keyboard_xt_zenith_device); + + nmi_init(); + +} + +const device_t * +z184_get_device(void) +{ + return &cga_device; +} + +/* + * Current bugs and limitations: + * - missing NVRAM implementation + */ int -machine_xt_zenith_init(const machine_t *model) +machine_xt_z184_init(const machine_t *model) { int ret; @@ -114,22 +144,61 @@ machine_xt_zenith_init(const machine_t *model) 0x000f8000, 32768, 0); if (bios_only || !ret) - return ret; + return ret; - machine_common_init(model); - - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); + machine_zenith_init(model); lpt1_remove(); /* only one parallel port */ lpt2_remove(); lpt1_init(0x278); device_add(&i8250_device); serial_set_next_inst(2); /* So that serial_standalone_init() won't do anything. */ - device_add(&zenith_scratchpad_device); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); - device_add(&keyboard_xt_compaq_device); - nmi_init(); - + + device_add(&cga_device); + return ret; } + +int +machine_xt_z151_init(const machine_t *model) +{ + int ret; + ret = bios_load_linear(L"roms/machines/zdsz151/444-229-18.bin", + 0x000fc000, 32768, 0); + if (ret) { + bios_load_aux_linear(L"roms/machines/zdsz151/444-260-18.bin", + 0x000f8000, 16384, 0); + } + + if (bios_only || !ret) + return ret; + + machine_zenith_init(model); + + return ret; +} + +/* + * Current bugs and limitations: + * - Memory board support for EMS currently missing + */ +int +machine_xt_z159_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/zdsz159/z159m v2.9e.10d", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + machine_zenith_init(model); + + /* parallel port is on the memory board */ + lpt1_remove(); /* only one parallel port */ + lpt2_remove(); + lpt1_init(0x278); + + return ret; +} \ No newline at end of file diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c852b0057..5504b69a3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -56,6 +56,8 @@ const machine_type_t machine_types[] = { const machine_t machines[] = { /* 8088 Machines */ + { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, + { "[8088] Eagle PC Spirit", "eagle_pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_eaglepcspirit_init, NULL }, { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, { "[8088] IBM PC (1982)", "ibmpc82", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 256, 256, 0, machine_pc82_init, NULL }, { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, @@ -79,7 +81,9 @@ const machine_t machines[] = { { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, #endif { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, - { "[8088] Zenith Data SupersPort", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_zenith_init, NULL }, + { "[8088] Zenith Data Systems Z-151/152/161", "zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, + { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, + { "[8088] Zenith Data Systems SupersPort (Z-184)", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC|MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device }, /* 8086 Machines */ { "[8086] Amstrad PC1512", "pc1512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 8000000, 8000000, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, From bb93b7efba1ddd531ce2da1ee5adda412e8de2aa Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 19 Dec 2020 12:35:01 +0100 Subject: [PATCH 09/60] Redid the XT keyboard arrow keys handling to more closely match what a real 101/102-key keyboard does when in XT mode. --- src/device/keyboard_xt.c | 48 ++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 7af93103d..a7a837189 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -432,44 +432,30 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) } keyboard_get_states(NULL, &num_lock, NULL); - shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; + shift_states = keyboard_get_shift() & STATE_LSHIFT; if (is_amstrad) num_lock = !num_lock; + /* If NumLock is on, invert the left shift state so we can always check for + the the same way flag being set (and with NumLock on that then means it + is actually *NOT* set). */ + if (num_lock) + shift_states ^= STATE_LSHIFT; + switch(val) { case FAKE_LSHIFT_ON: - if (num_lock) { - if (!shift_states) { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - adddata(0x2a); - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - adddata(0xaa); - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - adddata(0xb6); - } + /* If NumLock is on, fake shifts are sent when shift is *NOT* presed, + if NumLock is off, fake shifts are sent when shift is pressed. */ + if (shift_states) { + /* Send fake shift. */ + adddata(num_lock ? 0x2a : 0xaa); } break; case FAKE_LSHIFT_OFF: - if (num_lock) { - if (!shift_states) { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - adddata(0xaa); - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - adddata(0x2a); - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - adddata(0x36); - } + if (shift_states) { + /* Send fake shift. */ + adddata(num_lock ? 0xaa : 0x2a); } break; default: @@ -521,13 +507,13 @@ kbd_write(uint16_t port, uint8_t val, void *priv) #ifdef ENABLE_KEYBOARD_XT_LOG if (kbd->type <= 1) - kbd_log("Casette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); + kbd_log("Cassette motor is %s\n", !(val & 0x08) ? "ON" : "OFF"); #endif break; #ifdef ENABLE_KEYBOARD_XT_LOG case 0x62: if (kbd->type <= 1) - kbd_log("Casette IN is %i\n", !!(val & 0x10)); + kbd_log("Cassette IN is %i\n", !!(val & 0x10)); break; #endif } From 0626c0a698be5e96db701e40073c6953422e8b3c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 8 Dec 2020 22:56:45 +0100 Subject: [PATCH 10/60] S3 Vision968 work. --- src/include/86box/vid_svga.h | 6 + src/include/86box/video.h | 4 + src/video/vid_ibm_rgb525_ramdac.c | 978 ++++++++++++++++++++++ src/video/vid_s3.c | 1255 +++++++++++++++++++++++++---- src/video/vid_table.c | 4 + src/win/Makefile.mingw | 2 +- 6 files changed, 2077 insertions(+), 172 deletions(-) create mode 100644 src/video/vid_ibm_rgb525_ramdac.c diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 14883f315..5d3d99bd3 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -217,6 +217,11 @@ extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t extern void bt48x_recalctimings(void *p, svga_t *svga); extern void bt48x_hwcursor_draw(svga_t *svga, int displine); +extern void ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void ibm_rgb525_recalctimings(void *p, svga_t *svga); +extern void ibm_rgb525_hwcursor_draw(svga_t *svga, int displine); + extern void icd2061_write(void *p, int val); extern float icd2061_getclock(int clock, void *p); @@ -259,6 +264,7 @@ extern const device_t bt485_ramdac_device; extern const device_t att20c505_ramdac_device; extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; +extern const device_t ibm_rgb525_ramdac_device; extern const device_t ics2494an_305_device; extern const device_t ics2595_device; extern const device_t icd2061_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 8b1917ae5..2079265c2 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -328,6 +328,10 @@ extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_vlb_device; extern const device_t s3_trio64v2_dx_pci_device; /* S3 ViRGE */ diff --git a/src/video/vid_ibm_rgb525_ramdac.c b/src/video/vid_ibm_rgb525_ramdac.c new file mode 100644 index 000000000..e6ba89e77 --- /dev/null +++ b/src/video/vid_ibm_rgb525_ramdac.c @@ -0,0 +1,978 @@ +/* + * 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. + * + * Emulation of the IBM RGB 525 true colour RAMDAC. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> + + +typedef union { + uint8_t pixel; + struct { + uint8_t b :2, g :3, r :2; + }; +} ibm_rgb525_pixel8_t; + +typedef union { + uint16_t pixel; + struct { + uint16_t b_ :5, g_ :6, r_ :5; + }; + struct { + uint16_t b :5, g :5, r :5, c :1; + }; +} ibm_rgb525_pixel16_t; + +typedef union { + uint32_t pixel; + struct { + uint8_t b, g, r, a; + }; +} ibm_rgb525_pixel32_t; + +typedef struct +{ + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t indexed_data[2048]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + uint8_t palettes[3][256]; + ibm_rgb525_pixel32_t extra_pal[4]; + int hwc_y, hwc_x; + uint16_t index, smlc_part; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status, indx_cntl; + uint8_t cursor_array; +} ibm_rgb525_ramdac_t; + + +void +ibm_rgb525_render_4bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 31)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + if (swap_nib) + dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf; + else + dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; + } else if (vram_size == 1) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + if (swap_nib) + dat = (dat64 >> ((x & 15) << 2)) & 0xf; + else + dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; + } else { + if (!(x & 7)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + if (swap_nib) + dat = (dat32 >> ((x & 7) << 2)) & 0xf; + else + dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][partition | dat]; + dat_out.g = ramdac->palettes[1][partition | dat]; + dat_out.b = ramdac->palettes[2][partition | dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 31) == 31)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + if ((vram_size == 1) && ((x & 15) == 15)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 7) == 7)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_8bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; + } else if (vram_size == 1) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 7) << 3)) & 0xff; + } else { + if (!(x & 3)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 3) << 3)) & 0xff; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][dat]; + dat_out.g = ramdac->palettes[1][dat]; + dat_out.b = ramdac->palettes[2][dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 3) == 3)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_15_16bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel16_t *dat_ex; + ibm_rgb525_pixel32_t dat_out; + uint16_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (b555_565 && (b16_dcol != 0x01)) + partition &= 0xc0; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 2) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; + } else if (vram_size == 1) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 3) << 4)) & 0xffff; + } else { + if (!(x & 1)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 1) << 4)) & 0xffff; + } + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel16_t *) &dat; + if (b555_565 && (b16_dcol != 0x01)) { + if (swaprb) { + temp = dat_ex->r_; + dat_ex->r_ = dat_ex->b_; + dat_ex->b_ = temp; + } + if (b16_dcol == 0x00) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r_]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g_]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b_]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2]; + dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_16to32[dat_ex->pixel]; + } else { + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (by16_pol) + dat ^= 0x8000; + if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g << 3]; + dat_out.b = ramdac->palettes[2][dat_ex->b << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff]; + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 7) == 7)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 3) == 3)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size && ((x & 1) == 1)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_24bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat; + uint64_t dat64[6]; + uint8_t *dat8 = (uint8_t *) dat64; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if ((x & 15) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + dat64[3] = *(uint64_t *)(&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); + dat64[4] = *(uint64_t *)(&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); + dat64[5] = *(uint64_t *)(&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL); + dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL); + dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 15) * 3)]); + } else if (vram_size == 1) { + if ((x & 7) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 7) * 3)]); + } else + dat = 0x00000000; + } else + dat = 0x00000000; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (b24_dcol == 0x00) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 48) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 24) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_32bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; + uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else if (vram_size == 1) { + if (!(x & 1)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else + dat = *(uint32_t *)(&svga->vram[svga->ma]); + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if ((b32_dcol < 0x03) && (by32_pol)) + dat ^= 0x01000000; + if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 3) == 3)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 1) == 1)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +static void +ibm_rgb525_set_bpp(ibm_rgb525_ramdac_t *ramdac, svga_t *svga) +{ + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + + if (ramdac->indexed_data[0x071] & 0x01) + switch (ramdac->indexed_data[0x00a] & 0x07) { + case 0x02: + svga->bpp = 4; + break; + case 0x03: + default: + svga->bpp = 8; + break; + case 0x04: + if (b555_565 && (b16_dcol != 0x01)) + svga->bpp = 16; + else + svga->bpp = 15; + break; + case 0x05: + svga->bpp = 24; + break; + case 0x06: + svga->bpp = 32; + break; + } else + svga->bpp = 8; + + // pclog("svga->bpp = %i\n", svga->bpp); + + svga_recalctimings(svga); +} + + +void +ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); + rs |= (!!rs2 << 2); + + // pclog("[%04X:%08X] [W] RS%01X = %02X\n", CS, cpu_state.pc, rs, val); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x03: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + index = svga->dac_addr & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->palettes[svga->dac_pos][index] = val; + else + ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2; + svga_out(addr, val, svga); + break; + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x04: + // pclog("Index low: %02X\n", val); + ramdac->index = (ramdac->index & 0x0700) | val; + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x05: + // pclog("Index high: %02X\n", val); + ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x06: + // pclog("Indexed data [%03X]: %02X\n", ramdac->index, val); + if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) + ramdac->indexed_data[ramdac->index] = val; + switch (ramdac->index) { + case 0x00a: case 0x00c: + ibm_rgb525_set_bpp(ramdac, svga); + break; + case 0x030: + switch (val & 0xc0) { + case 0x00: + ramdac->smlc_part = 0x0100; + break; + case 0x40: + ramdac->smlc_part = 0x0200; + break; + case 0x80: + ramdac->smlc_part = 0x0300; + break; + case 0xc0: + ramdac->smlc_part = 0x0400; + break; + } + svga->dac_hwcursor.addr = ramdac->smlc_part; + svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32; + svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); + /* pclog("%ix%i cursor %sabled at DAC buffer address %02X\n", svga->dac_hwcursor.xsize, + svga->dac_hwcursor.ysize, svga->dac_hwcursor.ena ? "en" : "dis", + svga->dac_hwcursor.addr); + pclog("Pixel order %i, mode %i, update %s\n", !!(ramdac->indexed_data[0x30] & 0x20), + ramdac->indexed_data[0x30] & 0x03, (ramdac->indexed_data[0x30] & 0x08) ? "now" : "later"); */ + break; + case 0x031: + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0xff00) | val; + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x032: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0x00ff) | (val << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x033: + if (!updt_cntl) + break; + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0xff00) | val; + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + break; + case 0x034: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (updt_cntl) { + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0x00ff) | (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.x); + } else { + svga->dac_hwcursor.x = ramdac->indexed_data[0x031]; + svga->dac_hwcursor.x |= (ramdac->indexed_data[0x032] << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + svga->dac_hwcursor.y = ramdac->indexed_data[0x033]; + svga->dac_hwcursor.y |= (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + } + break; + case 0x035: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.xoff = (val & 0x1f); + else + svga->dac_hwcursor.xoff = (val & 0x3f); + // pclog("Cursor X offset = %i\n", (int) svga->dac_hwcursor.xoff); + break; + case 0x036: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.yoff = (val & 0x1f); + else + svga->dac_hwcursor.yoff = (val & 0x3f); + // pclog("Cursor Y offset = %i\n", (int) svga->dac_hwcursor.yoff); + break; + case 0x040: case 0x043: case 0x046: + ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; + break; + case 0x041: case 0x044: case 0x047: + ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val; + break; + case 0x042: case 0x045: case 0x048: + ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val; + break; + case 0x060: + ramdac->extra_pal[3].r = val; + break; + case 0x061: + ramdac->extra_pal[3].g = val; + break; + case 0x062: + ramdac->extra_pal[3].b = val; + break; + case 0x071: + svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; + ibm_rgb525_set_bpp(ramdac, svga); + break; + default: + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + // pclog("Index now: %03X\n", ramdac->index); + } + break; + case 0x07: + ramdac->indx_cntl = val & 0x01; + break; + } + + return; +} + + +uint8_t +ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); + rs |= (!!rs2 << 2); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga->dac_addr & 0xff; + if (ramdac->indexed_data[0x070] & 0x20) + temp = (temp & 0xfc) | svga->dac_status; + break; + case 0x04: + temp = ramdac->index & 0xff; + break; + case 0x05: + temp = ramdac->index >> 8; + break; + case 0x06: + temp = ramdac->indexed_data[ramdac->index]; + switch (ramdac->index) { + case 0x0000: /* Revision */ + temp = 0xe0; + break; + case 0x0001: /* ID */ + temp = 0x02; + break; + case 0x0031: + if (loc_read) + temp = svga->dac_hwcursor.x & 0xff; + break; + case 0x0032: + if (loc_read) + temp = svga->dac_hwcursor.x >> 8; + break; + case 0x0033: + if (loc_read) + temp = svga->dac_hwcursor.y & 0xff; + break; + case 0x0034: + if (loc_read) + temp = svga->dac_hwcursor.y >> 8; + break; + default: + temp = ramdac->indexed_data[ramdac->index]; + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + } + break; + case 0x07: + temp = ramdac->indx_cntl; + break; + } + + // pclog("[%04X:%08X] [R] RS%01X = %02X\n", CS, cpu_state.pc, rs, temp); + + return temp; +} + + +void +ibm_rgb525_recalctimings(void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + + svga->interlace = ramdac->indexed_data[0x071] & 0x20; + + if (svga->scrblank || !svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) { + if (ramdac->indexed_data[0x071] & 0x01) { + switch (svga->bpp) { + case 4: + svga->render = ibm_rgb525_render_4bpp; + break; + case 8: + svga->render = ibm_rgb525_render_8bpp; + break; + case 15: case 16: + svga->render = ibm_rgb525_render_15_16bpp; + break; + case 24: + svga->render = ibm_rgb525_render_24bpp; + break; + case 32: + svga->render = ibm_rgb525_render_32bpp; + break; + } + } + } + } + } +} + + +void +ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) +{ + uint8_t dat, four_pixels = 0x00; + int x, pitch, x_pos, y_pos, offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + uint32_t *p; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; + uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; + + /* The planes come in one part, and each plane is 2bpp, + so a 32x32 cursor has 8 bytes per line, and a 64x64 + cursor has 16 bytes per line. */ + pitch = (svga->dac_hwcursor_latch.xsize >> 2); /* Bytes per line. */ + + if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + for (x = 0; x < svga->dac_hwcursor_latch.xsize; x ++) { + if (!(x & 3)) { + four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; + // pclog("Pixels %i to %i: %02X at %08X\n", x, x + 3, four_pixels, svga->dac_hwcursor_latch.addr); + } + if (pix_ordr) + dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; + else + dat = (four_pixels >> ((x & 3) << 1)) & 0x03; + + x_pos = offset + svga->x_add + x; + + switch (cursor_mode) { + case 0x01: + switch (dat) { + case 0x01: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x02: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Cursor Color 3 */ + p[x_pos] = ramdac->extra_pal[2].pixel; + break; + } + break; + case 0x02: + switch (dat) { + case 0x00: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x01: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Complement */ + p[x_pos] ^= 0xffffff; + break; + } + break; + case 0x03: + switch (dat) { + case 0x02: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x03: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + } + break; + } + + if ((x & 3) == 3) + svga->dac_hwcursor_latch.addr++; + } + + if ((ramdac->indexed_data[0x071] & 0x20) && !svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; +} + + +void * +ibm_rgb525_ramdac_init(const device_t *info) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) malloc(sizeof(ibm_rgb525_ramdac_t)); + memset(ramdac, 0, sizeof(ibm_rgb525_ramdac_t)); + + ramdac->smlc_part = 0x0100; + + ramdac->indexed_data[0x0008] = 0x0001; + ramdac->indexed_data[0x0015] = 0x0008; + ramdac->indexed_data[0x0016] = 0x0041; + + return ramdac; +} + + +static void +ibm_rgb525_ramdac_close(void *priv) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + + +const device_t ibm_rgb525_ramdac_device = +{ + "IBM RGB525 RAMDAC", + 0, 0, + ibm_rgb525_ramdac_init, ibm_rgb525_ramdac_close, + NULL, { NULL }, NULL, NULL, NULL +}; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 4d61f9424..dafd25ebc 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -52,6 +52,8 @@ #define ROM_TRIO64V2_DX_VBE20 L"roms/video/s3/86c775_2.bin" #define ROM_PHOENIX_TRIO64VPLUS L"roms/video/s3/64V1506.ROM" #define ROM_DIAMOND_STEALTH_SE L"roms/video/s3/DiamondStealthSE.VBI" +#define ROM_ELSAWIN2KPROX_964 L"roms/video/s3/elsaw20004m.BIN" +#define ROM_ELSAWIN2KPROX L"roms/video/s3/elsaw20008m.BIN" enum { @@ -72,7 +74,9 @@ enum S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, S3_DIAMOND_STEALTH_SE, - S3_DIAMOND_STEALTH_VRAM + S3_DIAMOND_STEALTH_VRAM, + S3_ELSAWIN2KPROX_964, + S3_ELSAWIN2KPROX }; @@ -84,11 +88,12 @@ enum S3_86C801 = 0x06, S3_86C805 = 0x07, S3_VISION964 = 0x08, - S3_VISION864 = 0x10, - S3_TRIO32 = 0x18, - S3_TRIO64 = 0x20, - S3_TRIO64V = 0x28, - S3_TRIO64V2 = 0x30 + S3_VISION968 = 0x10, + S3_VISION864 = 0x18, + S3_TRIO32 = 0x20, + S3_TRIO64 = 0x28, + S3_TRIO64V = 0x30, + S3_TRIO64V2 = 0x38 }; @@ -101,6 +106,8 @@ static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, static video_timings_t timing_s3_vision864_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_vision964_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_vision964_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_trio32_vlb = {VIDEO_BUS, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio32_pci = {VIDEO_PCI, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio64_vlb = {VIDEO_BUS, 3, 2, 4, 25, 25, 40}; @@ -176,6 +183,8 @@ typedef struct s3_t uint32_t vram_mask; uint8_t data_available; + int card_type; + struct { uint16_t subsys_cntl; @@ -183,13 +192,15 @@ typedef struct s3_t uint8_t advfunc_cntl; uint16_t cur_y, cur_y2; uint16_t cur_x, cur_x2; - uint16_t x2; + uint16_t x2, ropmix; + uint16_t pat_x, pat_y; 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 cmd, cmd2; uint16_t short_stroke; + uint32_t pat_bg_color, pat_fg_color; uint32_t bkgd_color; uint32_t frgd_color; uint32_t wrt_mask; @@ -202,12 +213,14 @@ typedef struct s3_t uint8_t pix_trans[4]; int cx, cy; + int px, py; int sx, sy; int dx, dy; uint32_t src, dest, pattern; int poly_cx, poly_cx2; int poly_cy, poly_cy2; + int poly_line_cx; int point_1_updated, point_2_updated; int poly_dx1, poly_dx2; int poly_x; @@ -300,6 +313,9 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p); static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); static uint8_t s3_accel_in(uint16_t port, void *p); +static uint8_t s3_pci_read(int func, int addr, void *p); +static void s3_pci_write(int func, int addr, uint8_t val, void *p); + static __inline void wake_fifo_thread(s3_t *s3) @@ -322,10 +338,11 @@ s3_update_irqs(s3_t *s3) if (!s3->pci) return; - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { pci_set_irq(s3->card, PCI_INTA); - else + } 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); @@ -403,26 +420,24 @@ s3_data_len(s3_t *s3) static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { - svga_t *svga = &s3->svga; - if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + } else if (s3->accel.cmd & 0x400) s3_accel_start(32, 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + else if (s3->accel.cmd & 0x400) s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); else s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); @@ -432,18 +447,18 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) -{ +{ if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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) { + } 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); @@ -459,9 +474,9 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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) { + 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 { @@ -474,9 +489,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) -{ - svga_t *svga = &s3->svga; - +{ switch (port) { case 0x8148: case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; @@ -594,11 +607,18 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.b2e8_pix = 0; break; case 0x9949: case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3_accel_start(-1, 0, 0xffffffff, 0, s3); s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ break; + case 0x994a: case 0x9aea: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff00) | val; + break; + case 0x994b: case 0x9aeb: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff) | (val << 8); + break; + case 0x9d48: case 0x9ee8: s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; @@ -802,6 +822,95 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; break; + case 0xd148: case 0xd2e8: + s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; + break; + case 0xd149: case 0xd2e9: + s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); + break; + case 0xe548: case 0xe6e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + break; + case 0xe549: case 0xe6e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xe54a: case 0xe6ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + } + break; + case 0xe54b: case 0xe6eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe948: case 0xeae8: + s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; + break; + case 0xe949: case 0xeae9: + s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); + break; + case 0xe94a: case 0xeaea: + s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; + break; + case 0xe94b: case 0xeaeb: + s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); + break; + case 0xed48: case 0xeee8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + break; + case 0xed49: case 0xeee9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xed4a: case 0xeeea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + } + break; + case 0xed4b: case 0xeeeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe148: case 0xe2e8: s3->accel.b2e8_pix = 0; if (s3_cpu_dest(s3)) @@ -831,11 +940,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } @@ -855,8 +963,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; } } @@ -887,7 +994,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { 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); @@ -940,10 +1047,17 @@ static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { svga_t *svga = &s3->svga; - + if (s3->packed_mmio) { int addr_lo = addr & 1; - switch (addr & 0xfffe) { + if (svga->crtc[0x53] & 0x08) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + s3_pci_write(0, addr & 0xff, val, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + s3_out(addr & 0xfff, val, s3); + } + + switch (addr & 0x1fffe) { case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ case 0x8102: addr = 0x86e8; break; @@ -1019,12 +1133,25 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x814a: addr = 0x96e8; break; case 0x814c: addr = 0x96ea; break; + case 0x8150: addr = 0xd2e8; break; + + case 0x8154: addr = 0x8ee8; break; + case 0x8156: addr = 0x96e8; break; + + case 0x8164: case 0x8166: + WRITE8(addr, s3->accel.pat_bg_color, val); + return; + case 0x8168: addr = 0xeae8; break; case 0x816a: addr = 0xeaea; break; + + case 0x816c: case 0x816e: + WRITE8(addr, s3->accel.pat_fg_color, val); + return; } addr |= addr_lo; } - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xffff) < 0x8000) { if (s3->accel.cmd & 0x100) { @@ -1088,7 +1215,7 @@ static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { svga_t *svga = &s3->svga; - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xfffe) < 0x8000) { s3_accel_out_pixtrans_w(s3, val); @@ -1123,7 +1250,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) if ((addr & 0xfffc) < 0x8000) { s3_accel_out_pixtrans_l(s3, val); } else { - switch (addr & 0xfffc) { + switch (addr & 0xfffc) { case 0x8180: s3->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1254,13 +1381,16 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3_accel_write_fifo(s3, addr, val); break; + case 0x18080: + break; + default: 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); break; - } + } } } else { if (addr & 0x8000) { @@ -1732,7 +1862,7 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1745,7 +1875,11 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } static void @@ -1775,7 +1909,11 @@ s3_io_remove(s3_t *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(0xd2e8, 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(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); s3_io_remove_alt(s3); } @@ -1783,13 +1921,18 @@ s3_io_remove(s3_t *s3) static void s3_io_set_alt(s3_t *s3) { + svga_t *svga = &s3->svga; + if (!s3->translate) return; + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1807,7 +1950,10 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } - io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_VISION968) + io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1821,19 +1967,30 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } } static void s3_io_set(s3_t *s3) { + svga_t *svga = &s3->svga; + s3_io_remove(s3); io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + 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); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { 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); @@ -1851,7 +2008,10 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) + io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + 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); @@ -1865,6 +2025,12 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } s3_io_set_alt(s3); } @@ -1883,7 +2049,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); } @@ -1906,6 +2072,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; + } else if (svga->seqaddr == 9) { + svga->seqregs[svga->seqaddr] = val & 0x80; + s3_io_set(s3); + return; + } else if (svga->seqaddr == 0xa) { + svga->seqregs[svga->seqaddr] = val & 0x80; + return; } break; @@ -1916,13 +2089,15 @@ s3_out(uint16_t addr, uint8_t val, void *p) rs2 = (svga->crtc[0x55] & 0x01); if (s3->chip >= S3_TRIO32) svga_out(addr, val, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) rs3 = !!(svga->crtc[0x55] & 0x02); else rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + ibm_rgb525_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) att49x_ramdac_out(addr, val, svga->ramdac, svga); else if (s3->chip < S3_86C928) sc1148x_ramdac_out(addr, val, svga->ramdac, svga); @@ -1972,7 +2147,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) 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 0x80: s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 4)) ? 1600 : 800; break; case 0x81: s3->width = 1600; break; case 0xc0: s3->width = 1280; break; } @@ -2020,13 +2195,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x45: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.ena = val & 1; break; case 0x46: case 0x47: case 0x48: case 0x49: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; @@ -2073,6 +2248,9 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x53: case 0x58: case 0x59: case 0x5a: + if (svga->crtcreg == 0x59) + pclog("0x59 write val = %02x\n", val); + s3_updatemapping(s3); break; @@ -2088,8 +2266,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) } break; + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + break; + case 0x42: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } @@ -2161,10 +2344,12 @@ s3_in(uint16_t addr, void *p) rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) return svga_in(addr, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + return ibm_rgb525_ramdac_in(addr, rs2, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) return att49x_ramdac_in(addr, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, svga->ramdac, svga); @@ -2186,18 +2371,24 @@ s3_in(uint16_t addr, void *p) 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 0x5c: /* General Output Port Register */ - temp = svga->crtc[svga->crtcreg] & 0xf0; - if (((svga->miscout >> 2) & 3) == 3) + temp = svga->crtc[svga->crtcreg] & 0xa0; + if (((svga->miscout >> 2) & 3) == 3) temp |= svga->crtc[0x42] & 0x0f; - else + else temp |= ((svga->miscout >> 2) & 3); - return temp; + if ((temp & 0xa0) == 0xa0) { + if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) + temp |= 0x40; + if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) + temp |= 0x10; + } + return temp; case 0x69: return s3->ma_ext; case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; - case 0x6c: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); + case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); } return svga->crtc[svga->crtcreg]; } @@ -2226,8 +2417,13 @@ static void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) - bt48x_recalctimings(svga->ramdac, svga); + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if (s3->card_type == S3_ELSAWIN2KPROX_964) + ibm_rgb525_recalctimings(svga->ramdac, svga); + else + bt48x_recalctimings(svga->ramdac, svga); + } else if (s3->chip == S3_VISION968) + ibm_rgb525_recalctimings(svga->ramdac, svga); else svga->interlace = svga->crtc[0x42] & 0x20; @@ -2247,36 +2443,45 @@ static void s3_recalctimings(svga_t *svga) switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; + if (s3->width == 1280) + svga->hdisp *= 2; break; case 15: svga->render = svga_render_15bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 16: svga->render = svga_render_16bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 24: svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) + if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805 && s3->chip != S3_VISION968) svga->hdisp /= 3; else svga->hdisp = (svga->hdisp * 2) / 3; break; case 32: svga->render = svga_render_32bpp_highres; - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_86C928)) + if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && + (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) svga->hdisp /= 4; + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; break; } } @@ -2467,16 +2672,23 @@ s3_updatemapping(s3_t *s3) mem_mapping_disable(&s3->linear_mapping); if (!(svga->crtc[0x53] & 0x10)) { + pclog("Linear mapping enabled at 0xa0000\n"); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; } } else { + if (s3->chip >= S3_TRIO64V) + s3->linear_base &= 0xfc000000; + else + s3->linear_base &= 0xfe000000; + pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { + pclog("Linear mapping disabled\n"); mem_mapping_disable(&s3->linear_mapping); } - + /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { mem_mapping_disable(&svga->mapping); @@ -2486,17 +2698,22 @@ s3_updatemapping(s3_t *s3) else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); } else { + pclog("Standard MMIO enabled at 0xa0000\n"); mem_mapping_enable(&s3->mmio_mapping); } } else { + pclog("Standard MMIO disabled\n"); mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { + pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - } else - mem_mapping_disable(&s3->new_mmio_mapping); + } else { + pclog("New MMIO disabled\n", s3->linear_base); + mem_mapping_disable(&s3->new_mmio_mapping); + } } } @@ -2524,7 +2741,8 @@ s3_enable_fifo(s3_t *s3) if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) + (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || + (s3->chip == S3_VISION968)) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); @@ -2535,6 +2753,7 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; @@ -2564,6 +2783,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) break; case 0x4948: case 0x4ae8: s3->accel.advfunc_cntl = val; + if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) { + s3->width = (val & 4) ? 1600 : 800; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } s3_updatemapping(s3); break; } @@ -2871,6 +3095,48 @@ s3_accel_in(uint16_t port, void *p) } break; + case 0xd148: case 0xd2e8: + return s3->accel.ropmix & 0xff; + + case 0xd149: case 0xd2e9: + return s3->accel.ropmix >> 8; + + case 0xe548: case 0xe6e8: + return s3->accel.pat_bg_color & 0xff; + + case 0xe549: case 0xe6e9: + return s3->accel.pat_bg_color >> 8; + + case 0xe54a: case 0xe6ea: + return s3->accel.pat_bg_color >> 16; + + case 0xe54b: case 0xe6eb: + return s3->accel.pat_bg_color >> 24; + + case 0xe948: case 0xeae8: + return s3->accel.pat_y & 0xff; + + case 0xe949: case 0xeae9: + return s3->accel.pat_y >> 8; + + case 0xe94a: case 0xeaea: + return s3->accel.pat_x & 0xff; + + case 0xe94b: case 0xeaeb: + return s3->accel.pat_x >> 8; + + case 0xed48: case 0xeee8: + return s3->accel.pat_fg_color & 0xff; + + case 0xed49: case 0xeee9: + return s3->accel.pat_fg_color >> 8; + + case 0xed4a: case 0xeeea: + return s3->accel.pat_fg_color >> 16; + + case 0xed4b: case 0xeeeb: + return s3->accel.pat_fg_color >> 24; + case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; @@ -2984,11 +3250,17 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) + if (!s3->enable_8514) { return 0xff; + } - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xffff) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + return s3_pci_read(0, addr & 0xff, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + return s3_in(addr & 0xfff, s3); + + switch (addr & 0x1ffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: @@ -3006,6 +3278,9 @@ s3_accel_read(uint32_t addr, void *p) return s3->subsys_stat; case 0x8505: return s3->subsys_cntl; + /* Video engine status - currently a dummy. */ + case 0x1809c: case 0x1809d: case 0x1809e: case 0x1809f: + return 0x00; default: return s3_accel_in(addr & 0xffff, p); } @@ -3038,8 +3313,8 @@ s3_accel_read_w(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffe) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffe) { default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -3084,8 +3359,8 @@ s3_accel_read_l(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffffffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffc) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffc) { case 0x8180: temp = s3->streams.pri_ctrl; break; @@ -3241,6 +3516,7 @@ polygon_setup(s3_t *s3) } } + #define READ(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)]; @@ -3276,6 +3552,277 @@ polygon_setup(s3_t *s3) } + +#define ROPMIX_READ(D, P, S) \ + { \ + switch (rop) { \ + case 0x00: out = 0; break; \ + case 0x01: out = ~(D | (P | S)); break; \ + case 0x02: out = D & ~(P | S); break; \ + case 0x03: out = ~(P | S); break; \ + case 0x04: out = S & ~(D | P); break; \ + case 0x05: out = ~(D | P); break; \ + case 0x06: out = ~(P | ~(D ^ S)); break; \ + case 0x07: out = ~(P | (D & S)); break; \ + case 0x08: out = S & (D & ~P); break; \ + case 0x09: out = ~(P | (D ^ S)); break; \ + case 0x0a: out = D & ~P; break; \ + case 0x0b: out = ~(P | (S & ~D)); break; \ + case 0x0c: out = S & ~P; break; \ + case 0x0d: out = ~(P | (D & ~S)); break; \ + case 0x0e: out = ~(P | ~(D | S)); break; \ + case 0x0f: out = ~P; break; \ + case 0x10: out = P & ~(D | S); break; \ + case 0x11: out = ~(D | S); break; \ + case 0x12: out = ~(S | ~(D ^ P)); break; \ + case 0x13: out = ~(S | (D & P)); break; \ + case 0x14: out = ~(D | ~(P ^ S)); break; \ + case 0x15: out = ~(D | (P & S)); break; \ + case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ + case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ + case 0x18: out = (S ^ P) & (P ^ D); break; \ + case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ + case 0x1a: out = P ^ (D | (S & P)); break; \ + case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ + case 0x1c: out = P ^ (S | (D & P)); break; \ + case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ + case 0x1e: out = P ^ (D | S); break; \ + case 0x1f: out = ~(P & (D | S)); break; \ + case 0x20: out = D & (P & ~S); break; \ + case 0x21: out = ~(S | (D ^ P)); break; \ + case 0x22: out = D & ~S; break; \ + case 0x23: out = ~(S | (P & ~D)); break; \ + case 0x24: out = (S ^ P) & (D ^ S); break; \ + case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ + case 0x26: out = S ^ (D | (P & S)); break; \ + case 0x27: out = S ^ (D | ~(P ^ S)); break; \ + case 0x28: out = D & (P ^ S); break; \ + case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ + case 0x2a: out = D & ~(P & S); break; \ + case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ + case 0x2c: out = S ^ (P & (D | S)); break; \ + case 0x2d: out = P ^ (S | ~D); break; \ + case 0x2e: out = P ^ (S | (D ^ P)); break; \ + case 0x2f: out = ~(P & (S | ~D)); break; \ + case 0x30: out = P & ~S; break; \ + case 0x31: out = ~(S | (D & ~P)); break; \ + case 0x32: out = S ^ (D | (P | S)); break; \ + case 0x33: out = ~S; break; \ + case 0x34: out = S ^ (P | (D & S)); break; \ + case 0x35: out = S ^ (P | ~(D ^ S)); break; \ + case 0x36: out = S ^ (D | P); break; \ + case 0x37: out = ~(S & (D | P)); break; \ + case 0x38: out = P ^ (S & (D | P)); break; \ + case 0x39: out = S ^ (P | ~D); break; \ + case 0x3a: out = S ^ (P | (D ^ S)); break; \ + case 0x3b: out = ~(S & (P | ~D)); break; \ + case 0x3c: out = P ^ S; break; \ + case 0x3d: out = S ^ (P | ~(D | S)); break; \ + case 0x3e: out = S ^ (P | (D & ~S)); break; \ + case 0x3f: out = ~(P & S); break; \ + case 0x40: out = P & (S & ~D); break; \ + case 0x41: out = ~(D | (P ^ S)); break; \ + case 0x42: out = (S ^ D) & (P ^ D); break; \ + case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ + case 0x44: out = S & ~D; break; \ + case 0x45: out = ~(D | (P & ~S)); break; \ + case 0x46: out = D ^ (S | (P & D)); break; \ + case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ + case 0x48: out = S & (D ^ P); break; \ + case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ + case 0x4a: out = D ^ (P & (S | D)); break; \ + case 0x4b: out = P ^ (D | ~S); break; \ + case 0x4c: out = S & ~(D & P); break; \ + case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ + case 0x4e: out = P ^ (D | (S ^ P)); break; \ + case 0x4f: out = ~(P & (D | ~S)); break; \ + case 0x50: out = P & ~D; break; \ + case 0x51: out = ~(D | (S & ~P)); break; \ + case 0x52: out = D ^ (P | (S & D)); break; \ + case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ + case 0x54: out = ~(D | ~(P | S)); break; \ + case 0x55: out = ~D; break; \ + case 0x56: out = D ^ (P | S); break; \ + case 0x57: out = ~(D & (P | S)); break; \ + case 0x58: out = P ^ (D & (S | P)); break; \ + case 0x59: out = D ^ (P | ~S); break; \ + case 0x5a: out = D ^ P; break; \ + case 0x5b: out = D ^ (P | ~(S | D)); break; \ + case 0x5c: out = D ^ (P | (S ^ D)); break; \ + case 0x5d: out = ~(D & (P | ~S)); break; \ + case 0x5e: out = D ^ (P | (S & ~D)); break; \ + case 0x5f: out = ~(D & P); break; \ + case 0x60: out = P & (D ^ S); break; \ + case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ + case 0x62: out = D ^ (S & (P | D)); break; \ + case 0x63: out = S ^ (D | ~P); break; \ + case 0x64: out = S ^ (D & (P | S)); break; \ + case 0x65: out = D ^ (S | ~P); break; \ + case 0x66: out = D ^ S; break; \ + case 0x67: out = S ^ (D | ~(P | S)); break; \ + case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ + case 0x69: out = ~(P ^ (D ^ S)); break; \ + case 0x6a: out = D ^ (P & S); break; \ + case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ + case 0x6c: out = S ^ (D & P); break; \ + case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ + case 0x6e: out = S ^ (D & (P | ~S)); break; \ + case 0x6f: out = ~(P & ~(D ^ S)); break; \ + case 0x70: out = P & ~(D & S); break; \ + case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ + case 0x72: out = S ^ (D | (P ^ S)); break; \ + case 0x73: out = ~(S & (D | ~P)); break; \ + case 0x74: out = D ^ (S | (P ^ D)); break; \ + case 0x75: out = ~(D & (S | ~P)); break; \ + case 0x76: out = S ^ (D | (P & ~S)); break; \ + case 0x77: out = ~(D & S); break; \ + case 0x78: out = P ^ (D & S); break; \ + case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ + case 0x7a: out = D ^ (P & (S | ~D)); break; \ + case 0x7b: out = ~(S & ~(D ^ P)); break; \ + case 0x7c: out = S ^ (P & (D | ~S)); break; \ + case 0x7d: out = ~(D & ~(P ^ S)); break; \ + case 0x7e: out = (S ^ P) | (D ^ S); break; \ + case 0x7f: out = ~(D & (P & S)); break; \ + case 0x80: out = D & (P & S); break; \ + case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ + case 0x82: out = D & ~(P ^ S); break; \ + case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ + case 0x84: out = S & ~(D ^ P); break; \ + case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ + case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ + case 0x87: out = ~(P ^ (D & S)); break; \ + case 0x88: out = D & S; break; \ + case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ + case 0x8a: out = D & (S | ~P); break; \ + case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ + case 0x8c: out = S & (D | ~P); break; \ + case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ + case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ + case 0x8f: out = ~(P & ~(D & S)); break; \ + case 0x90: out = P & ~(D ^ S); break; \ + case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ + case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ + case 0x93: out = ~(S ^ (P & D)); break; \ + case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ + case 0x95: out = ~(D ^ (P & S)); break; \ + case 0x96: out = D ^ (P ^ S); break; \ + case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ + case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ + case 0x99: out = ~(D ^ S); break; \ + case 0x9a: out = D ^ (P & ~S); break; \ + case 0x9b: out = ~(S ^ (D & (P | S))); break; \ + case 0x9c: out = S ^ (P & ~D); break; \ + case 0x9d: out = ~(D ^ (S & (P | D))); break; \ + case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ + case 0x9f: out = ~(P & (D ^ S)); break; \ + case 0xa0: out = D & P; break; \ + case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ + case 0xa2: out = D & (P | ~S); break; \ + case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ + case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ + case 0xa5: out = ~(P ^ D); break; \ + case 0xa6: out = D ^ (S & ~P); break; \ + case 0xa7: out = ~(P ^ (D & (S | P))); break; \ + case 0xa8: out = D & (P | S); break; \ + case 0xa9: out = ~(D ^ (P | S)); break; \ + case 0xaa: out = D; break; \ + case 0xab: out = D | ~(P | S); break; \ + case 0xac: out = S ^ (P & (D ^ S)); break; \ + case 0xad: out = ~(D ^ (P | (S & D))); break; \ + case 0xae: out = D | (S & ~P); break; \ + case 0xaf: out = D | ~P; break; \ + case 0xb0: out = P & (D | ~S); break; \ + case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ + case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ + case 0xb3: out = ~(S & ~(D & P)); break; \ + case 0xb4: out = P ^ (S & ~D); break; \ + case 0xb5: out = ~(D ^ (P & (S | D))); break; \ + case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ + case 0xb7: out = ~(S & (D ^ P)); break; \ + case 0xb8: out = P ^ (S & (D ^ P)); break; \ + case 0xb9: out = ~(D ^ (S | (P & D))); break; \ + case 0xba: out = D | (P & ~S); break; \ + case 0xbb: out = D | ~S; break; \ + case 0xbc: out = S ^ (P & ~(D & S)); break; \ + case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ + case 0xbe: out = D | (P ^ S); break; \ + case 0xbf: out = D | ~(P & S); break; \ + case 0xc0: out = P & S; break; \ + case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ + case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ + case 0xc3: out = ~(P ^ S); break; \ + case 0xc4: out = S & (P | ~D); break; \ + case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ + case 0xc6: out = S ^ (D & ~P); break; \ + case 0xc7: out = ~(P ^ (S & (D | P))); break; \ + case 0xc8: out = S & (D | P); break; \ + case 0xc9: out = ~(S ^ (P | D)); break; \ + case 0xca: out = D ^ (P & (S ^ D)); break; \ + case 0xcb: out = ~(S ^ (P | (D & S))); break; \ + case 0xcc: out = S; break; \ + case 0xcd: out = S | ~(D | P); break; \ + case 0xce: out = S | (D & ~P); break; \ + case 0xcf: out = S | ~P; break; \ + case 0xd0: out = P & (S | ~D); break; \ + case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ + case 0xd2: out = P ^ (D & ~S); break; \ + case 0xd3: out = ~(S ^ (P & (D | S))); break; \ + case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ + case 0xd5: out = ~(D & ~(P & S)); break; \ + case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ + case 0xd7: out = ~(D & (P ^ S)); break; \ + case 0xd8: out = P ^ (D & (S ^ P)); break; \ + case 0xd9: out = ~(S ^ (D | (P & S))); break; \ + case 0xda: out = D ^ (P & ~(S & D)); break; \ + case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ + case 0xdc: out = S | (P & ~D); break; \ + case 0xdd: out = S | ~D; break; \ + case 0xde: out = S | (D ^ P); break; \ + case 0xdf: out = S | ~(D & P); break; \ + case 0xe0: out = P & (D | S); break; \ + case 0xe1: out = ~(P ^ (D | S)); break; \ + case 0xe2: out = D ^ (S & (P ^ D)); break; \ + case 0xe3: out = ~(P ^ (S | (D & P))); break; \ + case 0xe4: out = S ^ (D & (P ^ S)); break; \ + case 0xe5: out = ~(P ^ (D | (S & P))); break; \ + case 0xe6: out = S ^ (D & ~(P & S)); break; \ + case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ + case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ + case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ + case 0xea: out = D | (P & S); break; \ + case 0xeb: out = D | ~(P ^ S); break; \ + case 0xec: out = S | (D & P); break; \ + case 0xed: out = S | ~(D ^ P); break; \ + case 0xee: out = D | S; break; \ + case 0xef: out = S | (D | ~P); break; \ + case 0xf0: out = P; break; \ + case 0xf1: out = P | ~(D | S); break; \ + case 0xf2: out = P | (D & ~S); break; \ + case 0xf3: out = P | ~S; break; \ + case 0xf4: out = P | (S & ~D); break; \ + case 0xf5: out = P | ~D; break; \ + case 0xf6: out = P | (D ^ S); break; \ + case 0xf7: out = P | ~(D & S); break; \ + case 0xf8: out = P | (D & S); break; \ + case 0xf9: out = P | ~(D ^ S); break; \ + case 0xfa: out = D | P; break; \ + case 0xfb: out = D | (P | ~S); break; \ + case 0xfc: out = P | S; break; \ + case 0xfd: out = P | (S | ~D); break; \ + case 0xfe: out = D | (P | S); break; \ + case 0xff: out = ~0; break; \ + } \ + } + + +#define ROPMIX { \ + old_dest_dat = dest_dat; \ + ROPMIX_READ(dest_dat, pat_dat, src_dat); \ + out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } + + #define WRITE(addr, dat) if (s3->bpp == 0) \ { \ svga->vram[(addr) & s3->vram_mask] = dat; \ @@ -3298,6 +3845,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { svga_t *svga = &s3->svga; uint32_t src_dat = 0, dest_dat, old_dest_dat; + uint32_t out, pat_dat = 0; int frgd_mix, bkgd_mix; int clip_t = s3->accel.multifunc[1] & 0xfff; int clip_l = s3->accel.multifunc[2] & 0xfff; @@ -3308,6 +3856,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ uint16_t *vram_w = (uint16_t *)svga->vram; uint32_t *vram_l = (uint32_t *)svga->vram; uint32_t compare = s3->accel.color_cmp; + uint8_t rop = s3->accel.ropmix & 0xff; int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; @@ -3321,8 +3870,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((s3->chip >= S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968) && (s3->accel.cmd & (1 << 11))) { cmd |= 8; + } // SRC-BASE/DST-BASE if ((s3->accel.multifunc[0xd] >> 4) & 7) { @@ -3349,7 +3899,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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) { @@ -3377,7 +3927,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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 || s3->chip >= S3_TRIO64V) ? 0x80 : 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; @@ -3695,6 +4245,82 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } break; + + case 3: /*Polygon Fill Solid (Vision868/968 and Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + break; + + polygon_setup(s3); + + 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; + + 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 = dstbase + y * s3->width; + + while (x_count-- && count--) + { + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && + (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= 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; /*Not supported?*/ break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } + 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; + + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { @@ -3725,7 +4351,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7) { - while (1) + while (count-- && s3->accel.sy >= 0) { if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) @@ -3971,86 +4597,112 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } break; - - case 3: /*Polygon Fill Solid (Trio64 only)*/ - { - int end_y1, end_y2; + + case 9: /*Polyline/2-Point Line (Vision868/968 and Trio64 only)*/ + { + int error; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; - polygon_setup(s3); + if (!cpu_input) { + s3->accel.dx = ABS(s3->accel.destx_distp - s3->accel.cur_x); + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = ABS(s3->accel.desty_axstp - s3->accel.cur_y); + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~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; + } 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; - - 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 = dstbase + y * s3->width; - - while (x_count-- && count--) - { - if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && - (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) + if (s3->accel.dx > s3->accel.dy) { + error = s3->accel.dx / 2; + while (s3->accel.cx != s3->accel.destx_distp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= 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; /*Not supported?*/ break; - } + src_dat = s3->accel.frgd_color; if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.poly_x, dest_dat); - + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + MIX - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } - 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++; + error -= s3->accel.dy; + if (error < 0) { + error += s3->accel.dx; + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + } + + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; else - s3->accel.poly_x--; + s3->accel.cx--; } - - 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; + } else { + error = s3->accel.dy / 2; + while (s3->accel.cy != s3->accel.desty_axstp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) + { + src_dat = s3->accel.frgd_color; - case 11: /*Polygon Fill Pattern (Trio64 only)*/ + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + error -= s3->accel.dx; + if (error < 0) { + error += s3->accel.dy; + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; + else + s3->accel.cx--; + } + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + + } + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + + case 11: /*Polygon Fill Pattern (Vision868/968 and Trio64 only)*/ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; polygon_setup(s3); @@ -4133,6 +4785,144 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; } break; + + case 14: /*ROPBlt (Vision868/968 only)*/ + if (s3->chip != S3_VISION968) + break; + + 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.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.px = s3->accel.pat_x & 0xfff; + if (s3->accel.pat_x & 0x1000) s3->accel.px |= ~0xfff; + s3->accel.py = s3->accel.pat_y & 0xfff; + if (s3->accel.pat_y & 0x1000) s3->accel.py |= ~0xfff; + + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + } + + 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; + + while (count-- && s3->accel.sy >= 0) + { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= 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: READ(s3->accel.src + s3->accel.cx, src_dat); break; + } + + if (s3->accel.ropmix & 0x100) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.pat_bg_color; break; + case 1: pat_dat = s3->accel.pat_fg_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } else { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.bkgd_color; break; + case 1: pat_dat = s3->accel.frgd_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + ROPMIX + + WRITE(s3->accel.dest + s3->accel.dx, out); + } + } + + 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++; + s3->accel.px++; + } + else + { + s3->accel.cx--; + s3->accel.dx--; + s3->accel.px--; + } + 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; + s3->accel.px -= (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.px += (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++; + s3->accel.py++; + } + else + { + s3->accel.cy--; + s3->accel.dy--; + s3->accel.py--; + } + + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3->accel.sy--; + + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) { + return; + } + } + } + break; } } @@ -4150,7 +4940,11 @@ s3_pci_read(int func, int addr, void *p) case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; case PCI_REG_COMMAND: - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + if (s3->chip == S3_VISION968) + return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + else + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + break; case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -4158,13 +4952,13 @@ s3_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x00; /*Supports VGA interface*/ else return 0x01; break; case 0x0b: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x03; else return 0x00; @@ -4172,8 +4966,8 @@ s3_pci_read(int func, int addr, void *p) case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); - case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; + case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; @@ -4203,14 +4997,14 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x12: - if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2) { + if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968) { svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); } break; case 0x13: - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : val; + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968) ? (val & 0xfe) : val); s3_updatemapping(s3); break; @@ -4316,6 +5110,22 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; + case S3_ELSAWIN2KPROX_964: + bios_fn = ROM_ELSAWIN2KPROX_964; + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); + break; + case S3_ELSAWIN2KPROX: + bios_fn = ROM_ELSAWIN2KPROX; + chip = S3_VISION968; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + break; case S3_PHOENIX_TRIO32: bios_fn = ROM_PHOENIX_TRIO32; chip = S3_TRIO32; @@ -4432,7 +5242,7 @@ static void *s3_init(const device_t *info) mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - if (chip == S3_VISION964) + if (chip == S3_VISION964 || chip == S3_VISION968) svga_init(info, &s3->svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, @@ -4456,8 +5266,10 @@ static void *s3_init(const device_t *info) svga->hwcursor.ysize = 64; - if (chip == S3_VISION964) + if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || chip == S3_VISION968) + svga->dac_hwcursor_draw = ibm_rgb525_hwcursor_draw; if (chip >= S3_VISION964) { switch (vram) { @@ -4489,13 +5301,20 @@ static void *s3_init(const device_t *info) break; } } - - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + + if (chip == S3_VISION968) { + if (s3->pci) + svga->crtc[0x36] = 2 | (0 << 2) | (1 << 4); + else + svga->crtc[0x36] = 1 | (0 << 2) | (1 << 4); + } else { + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + } if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); @@ -4524,8 +5343,10 @@ static void *s3_init(const device_t *info) s3->fifo_thread = thread_create(fifo_thread, s3); s3->int_line = 0; + + s3->card_type = info->local; - switch(info->local) { + switch(s3->card_type) { case S3_ORCHID_86C911: case S3_DIAMOND_STEALTH_VRAM: svga->decode_mask = (1 << 20) - 1; @@ -4614,6 +5435,7 @@ static void *s3_init(const device_t *info) break; case S3_DIAMOND_STEALTH64_964: + case S3_ELSAWIN2KPROX_964: svga->decode_mask = (8 << 20) - 1; stepping = 0xd0; /*Vision964*/ s3->id = stepping; @@ -4621,10 +5443,33 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&bt485_ramdac_device); + svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb525_ramdac_device) : device_add(&bt485_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - break; + break; + + case S3_ELSAWIN2KPROX: + svga->decode_mask = (8 << 20) - 1; + s3->id = 0xe1; /*Vision968*/ + s3->id_ext = 0xb0; + s3->id_ext_pci = 0xf0; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + svga->ramdac = device_add(&ibm_rgb525_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; case S3_PHOENIX_TRIO32: case S3_DIAMOND_STEALTH_SE: @@ -4723,6 +5568,16 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } +static int s3_elsa_winner2000_pro_x_964_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX_964); +} + +static int s3_elsa_winner2000_pro_x_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX); +} + static int s3_phoenix_trio32_available(void) { return rom_present(ROM_PHOENIX_TRIO32); @@ -4855,7 +5710,7 @@ static const device_config_t s3_phoenix_trio32_config[] = } }; -static const device_config_t s3_phoenix_trio64_onboard_config[] = +static const device_config_t s3_standard_config[] = { { "memory", "Video memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4879,7 +5734,7 @@ static const device_config_t s3_phoenix_trio64_onboard_config[] = } }; -static const device_config_t s3_config[] = +static const device_config_t s3_968_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4987,7 +5842,7 @@ const device_t s3_metheus_86c928_isa_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_vlb_device = @@ -5001,7 +5856,7 @@ const device_t s3_metheus_86c928_vlb_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_pci_device = @@ -5015,7 +5870,7 @@ const device_t s3_metheus_86c928_pci_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_bahamas64_vlb_device = @@ -5057,7 +5912,7 @@ const device_t s3_diamond_stealth64_964_vlb_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_964_pci_device = @@ -5071,7 +5926,7 @@ const device_t s3_diamond_stealth64_964_pci_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_9fx_vlb_device = @@ -5170,7 +6025,7 @@ const device_t s3_phoenix_trio64_vlb_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64_onboard_pci_device = @@ -5184,7 +6039,7 @@ const device_t s3_phoenix_trio64_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64_pci_device = @@ -5198,7 +6053,7 @@ const device_t s3_phoenix_trio64_pci_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_vlb_device = @@ -5212,7 +6067,7 @@ const device_t s3_phoenix_trio64vplus_vlb_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_onboard_pci_device = @@ -5226,7 +6081,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_pci_device = @@ -5240,7 +6095,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_vlb_device = @@ -5254,7 +6109,7 @@ const device_t s3_phoenix_vision864_vlb_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_pci_device = @@ -5268,7 +6123,7 @@ const device_t s3_phoenix_vision864_pci_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_vlb_device = @@ -5299,6 +6154,63 @@ const device_t s3_diamond_stealth64_pci_device = s3_9fx_config }; +const device_t s3_elsa_winner2000_pro_x_964_pci_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_964_vlb_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_pci_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_vlb_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + + const device_t s3_trio64v2_dx_pci_device = { "S3 Trio64V2/DX PCI", @@ -5310,5 +6222,6 @@ const device_t s3_trio64v2_dx_pci_device = { s3_trio64v2_dx_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; + diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d675ab322..88304b797 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -129,6 +129,8 @@ video_cards[] = { { "stealth3d_3000_pci", &s3_virge_988_pci_device }, { "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) { "mystique", &mystique_device }, @@ -165,6 +167,8 @@ video_cards[] = { { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "elsawin2kprox_964_vlb", &s3_elsa_winner2000_pro_x_964_vlb_device }, + { "elsawin2kprox_vlb", &s3_elsa_winner2000_pro_x_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "n9_9fx_vlb", &s3_9fx_vlb_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index c7cba0b80..9cf52250d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -742,7 +742,7 @@ VIDOBJ := video.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ vid_s3.o vid_s3_virge.o \ - vid_sdac_ramdac.o \ + vid_ibm_rgb525_ramdac.o vid_sdac_ramdac.o \ vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o \ From 2c0a7113c39e46e4f9f890600d58344d9842600b Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Dec 2020 13:23:37 +0100 Subject: [PATCH 11/60] Fixed the new MMIO mapping size of the S3 Virge968, Paintbrush no longer hangs but does not display correctly, pending the implementation of the Video engine. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index dafd25ebc..8e2523bbb 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2709,7 +2709,7 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); + mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { pclog("New MMIO disabled\n", s3->linear_base); mem_mapping_disable(&s3->new_mmio_mapping); From d0bdee2d69fd6d50cca382234e3a20a95337278f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 15 Dec 2020 19:51:48 +0100 Subject: [PATCH 12/60] Fixed S3 linear mapping on Vision964 and earlier. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8e2523bbb..7f310a2d1 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2679,7 +2679,7 @@ s3_updatemapping(s3_t *s3) } else { if (s3->chip >= S3_TRIO64V) s3->linear_base &= 0xfc000000; - else + else if (s3->chip == S3_VISION968) s3->linear_base &= 0xfe000000; pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); From 66e2b9bc1bd9bf20704033bee0a97ef9b591e5a1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 19 Dec 2020 16:08:21 +0100 Subject: [PATCH 13/60] Uninverted Num Lock on Amstrad PC1512 and PC1640. --- src/machine/m_amstrad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 44904c0c8..48a97ad41 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2499,7 +2499,7 @@ machine_amstrad_init(const machine_t *model, int type) keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; keyboard_scan = 1; - keyboard_set_is_amstrad(1); + keyboard_set_is_amstrad(((type == AMS_PC1512) || (type == AMS_PC1640)) ? 0 : 1); io_sethandler(0x0078, 2, ms_read, NULL, NULL, ms_write, NULL, NULL, ams); From 645429e5f288c2e5350b25f13f7f3784980e0a49 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 8 Dec 2020 22:56:45 +0100 Subject: [PATCH 14/60] S3 Vision968 work. --- src/include/86box/vid_svga.h | 6 + src/include/86box/video.h | 4 + src/video/vid_ibm_rgb525_ramdac.c | 978 ++++++++++++++++++++++ src/video/vid_s3.c | 1255 +++++++++++++++++++++++++---- src/video/vid_table.c | 4 + src/win/Makefile.mingw | 2 +- 6 files changed, 2077 insertions(+), 172 deletions(-) create mode 100644 src/video/vid_ibm_rgb525_ramdac.c diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 14883f315..5d3d99bd3 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -217,6 +217,11 @@ extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t extern void bt48x_recalctimings(void *p, svga_t *svga); extern void bt48x_hwcursor_draw(svga_t *svga, int displine); +extern void ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void ibm_rgb525_recalctimings(void *p, svga_t *svga); +extern void ibm_rgb525_hwcursor_draw(svga_t *svga, int displine); + extern void icd2061_write(void *p, int val); extern float icd2061_getclock(int clock, void *p); @@ -259,6 +264,7 @@ extern const device_t bt485_ramdac_device; extern const device_t att20c505_ramdac_device; extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; +extern const device_t ibm_rgb525_ramdac_device; extern const device_t ics2494an_305_device; extern const device_t ics2595_device; extern const device_t icd2061_device; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 8b1917ae5..2079265c2 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -328,6 +328,10 @@ extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_964_vlb_device; +extern const device_t s3_elsa_winner2000_pro_x_pci_device; +extern const device_t s3_elsa_winner2000_pro_x_vlb_device; extern const device_t s3_trio64v2_dx_pci_device; /* S3 ViRGE */ diff --git a/src/video/vid_ibm_rgb525_ramdac.c b/src/video/vid_ibm_rgb525_ramdac.c new file mode 100644 index 000000000..e6ba89e77 --- /dev/null +++ b/src/video/vid_ibm_rgb525_ramdac.c @@ -0,0 +1,978 @@ +/* + * 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. + * + * Emulation of the IBM RGB 525 true colour RAMDAC. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/video.h> +#include <86box/vid_svga.h> + + +typedef union { + uint8_t pixel; + struct { + uint8_t b :2, g :3, r :2; + }; +} ibm_rgb525_pixel8_t; + +typedef union { + uint16_t pixel; + struct { + uint16_t b_ :5, g_ :6, r_ :5; + }; + struct { + uint16_t b :5, g :5, r :5, c :1; + }; +} ibm_rgb525_pixel16_t; + +typedef union { + uint32_t pixel; + struct { + uint8_t b, g, r, a; + }; +} ibm_rgb525_pixel32_t; + +typedef struct +{ + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t indexed_data[2048]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + uint8_t palettes[3][256]; + ibm_rgb525_pixel32_t extra_pal[4]; + int hwc_y, hwc_x; + uint16_t index, smlc_part; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status, indx_cntl; + uint8_t cursor_array; +} ibm_rgb525_ramdac_t; + + +void +ibm_rgb525_render_4bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 31)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + if (swap_nib) + dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf; + else + dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf; + } else if (vram_size == 1) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + if (swap_nib) + dat = (dat64 >> ((x & 15) << 2)) & 0xf; + else + dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf; + } else { + if (!(x & 7)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + if (swap_nib) + dat = (dat32 >> ((x & 7) << 2)) & 0xf; + else + dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][partition | dat]; + dat_out.g = ramdac->palettes[1][partition | dat]; + dat_out.b = ramdac->palettes[2][partition | dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 31) == 31)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + if ((vram_size == 1) && ((x & 15) == 15)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 7) == 7)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_8bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t dat_out; + uint8_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 15)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff; + } else if (vram_size == 1) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 7) << 3)) & 0xff; + } else { + if (!(x & 3)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 3) << 3)) & 0xff; + } + } else + dat = 0x00000000; + if (b8_dcol == 0x00) { + dat_out.a = 0x00; + dat_out.r = ramdac->palettes[0][dat]; + dat_out.g = ramdac->palettes[1][dat]; + dat_out.b = ramdac->palettes[2][dat]; + } else + dat_out.pixel = video_8togs[dat]; + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if ((!vram_size) && ((x & 3) == 3)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_15_16bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel16_t *dat_ex; + ibm_rgb525_pixel32_t dat_out; + uint16_t dat; + uint32_t dat32 = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01; + uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (b555_565 && (b16_dcol != 0x01)) + partition &= 0xc0; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 2) { + if (!(x & 7)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff; + } else if (vram_size == 1) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 3) << 4)) & 0xffff; + } else { + if (!(x & 1)) + dat32 = *(uint32_t *)(&svga->vram[svga->ma]); + dat = (dat32 >> ((x & 1) << 4)) & 0xffff; + } + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel16_t *) &dat; + if (b555_565 && (b16_dcol != 0x01)) { + if (swaprb) { + temp = dat_ex->r_; + dat_ex->r_ = dat_ex->b_; + dat_ex->b_ = temp; + } + if (b16_dcol == 0x00) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r_]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g_]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b_]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2]; + dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_16to32[dat_ex->pixel]; + } else { + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (by16_pol) + dat ^= 0x8000; + if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) { + dat_out.a = 0x00; + if (bspr_cnt) { + dat_out.r = ramdac->palettes[0][partition | dat_ex->r]; + dat_out.g = ramdac->palettes[1][partition | dat_ex->g]; + dat_out.b = ramdac->palettes[2][partition | dat_ex->b]; + } else { + dat_out.r = ramdac->palettes[0][dat_ex->r << 3]; + dat_out.g = ramdac->palettes[1][dat_ex->g << 3]; + dat_out.b = ramdac->palettes[2][dat_ex->b << 3]; + } + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_out.r |= ((dat_out.r & 0xc0) >> 6); + dat_out.g |= ((dat_out.g & 0xc0) >> 6); + dat_out.b |= ((dat_out.b & 0xc0) >> 6); + } + } else + dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff]; + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff; + } else + p[x] = dat_out.pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 7) == 7)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 3) == 3)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size && ((x & 1) == 1)) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_24bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat; + uint64_t dat64[6]; + uint8_t *dat8 = (uint8_t *) dat64; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if ((x & 15) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + dat64[3] = *(uint64_t *)(&svga->vram[(svga->ma + 24) & svga->vram_display_mask]); + dat64[4] = *(uint64_t *)(&svga->vram[(svga->ma + 32) & svga->vram_display_mask]); + dat64[5] = *(uint64_t *)(&svga->vram[(svga->ma + 40) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL); + dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL); + dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 15) * 3)]); + } else if (vram_size == 1) { + if ((x & 7) == 0) { + dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + dat64[1] = *(uint64_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + dat64[2] = *(uint64_t *)(&svga->vram[(svga->ma + 16) & svga->vram_display_mask]); + if (swap_word) { + dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL); + dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL); + dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); + } + } + dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 7) * 3)]); + } else + dat = 0x00000000; + } else + dat = 0x00000000; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if (b24_dcol == 0x00) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 15) == 15)) + svga->ma = (svga->ma + 48) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 7) == 7)) + svga->ma = (svga->ma + 24) & svga->vram_display_mask; + } + } +} + + +void +ibm_rgb525_render_32bpp(svga_t *svga) +{ + int x; + uint32_t *p; + ibm_rgb525_pixel32_t *dat_ex; + uint32_t dat = 0x00000000; + uint64_t dat64 = 0x0000000000000000ULL; + uint64_t dat642 = 0x0000000000000000ULL; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; + uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; + uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; + uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; + uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01; + uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80, temp; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) { + p = &buffer32->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { + if (svga->crtc[0x17] & 0x80) { + if (vram_size == 3) { + if (!(x & 3)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + dat642 = *(uint64_t *)(&svga->vram[svga->ma + 8]); + if (swap_word) { + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL); + } + } + dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else if (vram_size == 1) { + if (!(x & 1)) { + dat64 = *(uint64_t *)(&svga->vram[svga->ma]); + if (swap_word) + dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL); + } + dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff; + } else + dat = *(uint32_t *)(&svga->vram[svga->ma]); + } else + dat = 0x00000000; + dat_ex = (ibm_rgb525_pixel32_t *) &dat; + if (swaprb) { + temp = dat_ex->r; + dat_ex->r = dat_ex->b; + dat_ex->b = temp; + } + if ((b32_dcol < 0x03) && (by32_pol)) + dat ^= 0x01000000; + if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) { + dat_ex->a = 0x00; + dat_ex->r = ramdac->palettes[0][dat_ex->r]; + dat_ex->g = ramdac->palettes[1][dat_ex->g]; + dat_ex->g = ramdac->palettes[2][dat_ex->b]; + if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) { + dat_ex->r |= ((dat_ex->r & 0xc0) >> 6); + dat_ex->g |= ((dat_ex->g & 0xc0) >> 6); + dat_ex->b |= ((dat_ex->b & 0xc0) >> 6); + } + } + if (svga->lowres) { + p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff; + } else + p[x] = dat_ex->pixel & 0xffffff; + + if ((vram_size == 3) && ((x & 3) == 3)) + svga->ma = (svga->ma + 16) & svga->vram_display_mask; + else if ((vram_size == 1) && ((x & 1) == 1)) + svga->ma = (svga->ma + 8) & svga->vram_display_mask; + else if (!vram_size) + svga->ma = (svga->ma + 4) & svga->vram_display_mask; + } + } +} + + +static void +ibm_rgb525_set_bpp(ibm_rgb525_ramdac_t *ramdac, svga_t *svga) +{ + uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; + uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; + + if (ramdac->indexed_data[0x071] & 0x01) + switch (ramdac->indexed_data[0x00a] & 0x07) { + case 0x02: + svga->bpp = 4; + break; + case 0x03: + default: + svga->bpp = 8; + break; + case 0x04: + if (b555_565 && (b16_dcol != 0x01)) + svga->bpp = 16; + else + svga->bpp = 15; + break; + case 0x05: + svga->bpp = 24; + break; + case 0x06: + svga->bpp = 32; + break; + } else + svga->bpp = 8; + + // pclog("svga->bpp = %i\n", svga->bpp); + + svga_recalctimings(svga); +} + + +void +ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint16_t index; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); + rs |= (!!rs2 << 2); + + // pclog("[%04X:%08X] [W] RS%01X = %02X\n", CS, cpu_state.pc, rs, val); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x03: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + case 0x01: /* Palette Data Register (RS value = 0001) */ + index = svga->dac_addr & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ramdac->palettes[svga->dac_pos][index] = val; + else + ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2; + svga_out(addr, val, svga); + break; + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + case 0x04: + // pclog("Index low: %02X\n", val); + ramdac->index = (ramdac->index & 0x0700) | val; + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x05: + // pclog("Index high: %02X\n", val); + ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); + if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) + ramdac->cursor_array = 1; + break; + case 0x06: + // pclog("Indexed data [%03X]: %02X\n", ramdac->index, val); + if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) + ramdac->indexed_data[ramdac->index] = val; + switch (ramdac->index) { + case 0x00a: case 0x00c: + ibm_rgb525_set_bpp(ramdac, svga); + break; + case 0x030: + switch (val & 0xc0) { + case 0x00: + ramdac->smlc_part = 0x0100; + break; + case 0x40: + ramdac->smlc_part = 0x0200; + break; + case 0x80: + ramdac->smlc_part = 0x0300; + break; + case 0xc0: + ramdac->smlc_part = 0x0400; + break; + } + svga->dac_hwcursor.addr = ramdac->smlc_part; + svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32; + svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); + /* pclog("%ix%i cursor %sabled at DAC buffer address %02X\n", svga->dac_hwcursor.xsize, + svga->dac_hwcursor.ysize, svga->dac_hwcursor.ena ? "en" : "dis", + svga->dac_hwcursor.addr); + pclog("Pixel order %i, mode %i, update %s\n", !!(ramdac->indexed_data[0x30] & 0x20), + ramdac->indexed_data[0x30] & 0x03, (ramdac->indexed_data[0x30] & 0x08) ? "now" : "later"); */ + break; + case 0x031: + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0xff00) | val; + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x032: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (!updt_cntl) + break; + svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0x00ff) | (val << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + break; + case 0x033: + if (!updt_cntl) + break; + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0xff00) | val; + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + break; + case 0x034: + /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ + val &= 0x8f; + if (val & 0x80) + val |= 0x70; + ramdac->indexed_data[ramdac->index] = val; + if (updt_cntl) { + svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0x00ff) | (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.x); + } else { + svga->dac_hwcursor.x = ramdac->indexed_data[0x031]; + svga->dac_hwcursor.x |= (ramdac->indexed_data[0x032] << 8); + // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); + svga->dac_hwcursor.y = ramdac->indexed_data[0x033]; + svga->dac_hwcursor.y |= (val << 8); + // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); + } + break; + case 0x035: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.xoff = (val & 0x1f); + else + svga->dac_hwcursor.xoff = (val & 0x3f); + // pclog("Cursor X offset = %i\n", (int) svga->dac_hwcursor.xoff); + break; + case 0x036: + if (svga->dac_hwcursor.xsize == 64) + svga->dac_hwcursor.yoff = (val & 0x1f); + else + svga->dac_hwcursor.yoff = (val & 0x3f); + // pclog("Cursor Y offset = %i\n", (int) svga->dac_hwcursor.yoff); + break; + case 0x040: case 0x043: case 0x046: + ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; + break; + case 0x041: case 0x044: case 0x047: + ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val; + break; + case 0x042: case 0x045: case 0x048: + ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val; + break; + case 0x060: + ramdac->extra_pal[3].r = val; + break; + case 0x061: + ramdac->extra_pal[3].g = val; + break; + case 0x062: + ramdac->extra_pal[3].b = val; + break; + case 0x071: + svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; + ibm_rgb525_set_bpp(ramdac, svga); + break; + default: + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + // pclog("Index now: %03X\n", ramdac->index); + } + break; + case 0x07: + ramdac->indx_cntl = val & 0x01; + break; + } + + return; +} + + +uint8_t +ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); + rs |= (!!rs2 << 2); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + temp = svga_in(addr, svga); + break; + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga->dac_addr & 0xff; + if (ramdac->indexed_data[0x070] & 0x20) + temp = (temp & 0xfc) | svga->dac_status; + break; + case 0x04: + temp = ramdac->index & 0xff; + break; + case 0x05: + temp = ramdac->index >> 8; + break; + case 0x06: + temp = ramdac->indexed_data[ramdac->index]; + switch (ramdac->index) { + case 0x0000: /* Revision */ + temp = 0xe0; + break; + case 0x0001: /* ID */ + temp = 0x02; + break; + case 0x0031: + if (loc_read) + temp = svga->dac_hwcursor.x & 0xff; + break; + case 0x0032: + if (loc_read) + temp = svga->dac_hwcursor.x >> 8; + break; + case 0x0033: + if (loc_read) + temp = svga->dac_hwcursor.y & 0xff; + break; + case 0x0034: + if (loc_read) + temp = svga->dac_hwcursor.y >> 8; + break; + default: + temp = ramdac->indexed_data[ramdac->index]; + break; + } + if (ramdac->indx_cntl) { + if (ramdac->index == 0x00ff) + ramdac->cursor_array = 0; + ramdac->index = (ramdac->index + 1) & 0x07ff; + } + break; + case 0x07: + temp = ramdac->indx_cntl; + break; + } + + // pclog("[%04X:%08X] [R] RS%01X = %02X\n", CS, cpu_state.pc, rs, temp); + + return temp; +} + + +void +ibm_rgb525_recalctimings(void *p, svga_t *svga) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + + svga->interlace = ramdac->indexed_data[0x071] & 0x20; + + if (svga->scrblank || !svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) { + if (ramdac->indexed_data[0x071] & 0x01) { + switch (svga->bpp) { + case 4: + svga->render = ibm_rgb525_render_4bpp; + break; + case 8: + svga->render = ibm_rgb525_render_8bpp; + break; + case 15: case 16: + svga->render = ibm_rgb525_render_15_16bpp; + break; + case 24: + svga->render = ibm_rgb525_render_24bpp; + break; + case 32: + svga->render = ibm_rgb525_render_32bpp; + break; + } + } + } + } + } +} + + +void +ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) +{ + uint8_t dat, four_pixels = 0x00; + int x, pitch, x_pos, y_pos, offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; + uint32_t *p; + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; + uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; + + /* The planes come in one part, and each plane is 2bpp, + so a 32x32 cursor has 8 bytes per line, and a 64x64 + cursor has 16 bytes per line. */ + pitch = (svga->dac_hwcursor_latch.xsize >> 2); /* Bytes per line. */ + + if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; + + y_pos = displine; + x_pos = offset + svga->x_add; + p = buffer32->line[y_pos]; + + for (x = 0; x < svga->dac_hwcursor_latch.xsize; x ++) { + if (!(x & 3)) { + four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; + // pclog("Pixels %i to %i: %02X at %08X\n", x, x + 3, four_pixels, svga->dac_hwcursor_latch.addr); + } + if (pix_ordr) + dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; + else + dat = (four_pixels >> ((x & 3) << 1)) & 0x03; + + x_pos = offset + svga->x_add + x; + + switch (cursor_mode) { + case 0x01: + switch (dat) { + case 0x01: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x02: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Cursor Color 3 */ + p[x_pos] = ramdac->extra_pal[2].pixel; + break; + } + break; + case 0x02: + switch (dat) { + case 0x00: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x01: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + case 0x03: + /* Complement */ + p[x_pos] ^= 0xffffff; + break; + } + break; + case 0x03: + switch (dat) { + case 0x02: + /* Cursor Color 1 */ + p[x_pos] = ramdac->extra_pal[0].pixel; + break; + case 0x03: + /* Cursor Color 2 */ + p[x_pos] = ramdac->extra_pal[1].pixel; + break; + } + break; + } + + if ((x & 3) == 3) + svga->dac_hwcursor_latch.addr++; + } + + if ((ramdac->indexed_data[0x071] & 0x20) && !svga->dac_hwcursor_oddeven) + svga->dac_hwcursor_latch.addr += pitch; +} + + +void * +ibm_rgb525_ramdac_init(const device_t *info) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) malloc(sizeof(ibm_rgb525_ramdac_t)); + memset(ramdac, 0, sizeof(ibm_rgb525_ramdac_t)); + + ramdac->smlc_part = 0x0100; + + ramdac->indexed_data[0x0008] = 0x0001; + ramdac->indexed_data[0x0015] = 0x0008; + ramdac->indexed_data[0x0016] = 0x0041; + + return ramdac; +} + + +static void +ibm_rgb525_ramdac_close(void *priv) +{ + ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) priv; + + if (ramdac) + free(ramdac); +} + + +const device_t ibm_rgb525_ramdac_device = +{ + "IBM RGB525 RAMDAC", + 0, 0, + ibm_rgb525_ramdac_init, ibm_rgb525_ramdac_close, + NULL, { NULL }, NULL, NULL, NULL +}; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 4d61f9424..dafd25ebc 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -52,6 +52,8 @@ #define ROM_TRIO64V2_DX_VBE20 L"roms/video/s3/86c775_2.bin" #define ROM_PHOENIX_TRIO64VPLUS L"roms/video/s3/64V1506.ROM" #define ROM_DIAMOND_STEALTH_SE L"roms/video/s3/DiamondStealthSE.VBI" +#define ROM_ELSAWIN2KPROX_964 L"roms/video/s3/elsaw20004m.BIN" +#define ROM_ELSAWIN2KPROX L"roms/video/s3/elsaw20008m.BIN" enum { @@ -72,7 +74,9 @@ enum S3_PHOENIX_TRIO64VPLUS, S3_PHOENIX_TRIO64VPLUS_ONBOARD, S3_DIAMOND_STEALTH_SE, - S3_DIAMOND_STEALTH_VRAM + S3_DIAMOND_STEALTH_VRAM, + S3_ELSAWIN2KPROX_964, + S3_ELSAWIN2KPROX }; @@ -84,11 +88,12 @@ enum S3_86C801 = 0x06, S3_86C805 = 0x07, S3_VISION964 = 0x08, - S3_VISION864 = 0x10, - S3_TRIO32 = 0x18, - S3_TRIO64 = 0x20, - S3_TRIO64V = 0x28, - S3_TRIO64V2 = 0x30 + S3_VISION968 = 0x10, + S3_VISION864 = 0x18, + S3_TRIO32 = 0x20, + S3_TRIO64 = 0x28, + S3_TRIO64V = 0x30, + S3_TRIO64V2 = 0x38 }; @@ -101,6 +106,8 @@ static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, static video_timings_t timing_s3_vision864_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_vision964_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_vision964_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; +static video_timings_t timing_s3_vision968_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_trio32_vlb = {VIDEO_BUS, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio32_pci = {VIDEO_PCI, 4, 3, 5, 26, 26, 42}; static video_timings_t timing_s3_trio64_vlb = {VIDEO_BUS, 3, 2, 4, 25, 25, 40}; @@ -176,6 +183,8 @@ typedef struct s3_t uint32_t vram_mask; uint8_t data_available; + int card_type; + struct { uint16_t subsys_cntl; @@ -183,13 +192,15 @@ typedef struct s3_t uint8_t advfunc_cntl; uint16_t cur_y, cur_y2; uint16_t cur_x, cur_x2; - uint16_t x2; + uint16_t x2, ropmix; + uint16_t pat_x, pat_y; 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 cmd, cmd2; uint16_t short_stroke; + uint32_t pat_bg_color, pat_fg_color; uint32_t bkgd_color; uint32_t frgd_color; uint32_t wrt_mask; @@ -202,12 +213,14 @@ typedef struct s3_t uint8_t pix_trans[4]; int cx, cy; + int px, py; int sx, sy; int dx, dy; uint32_t src, dest, pattern; int poly_cx, poly_cx2; int poly_cy, poly_cy2; + int poly_line_cx; int point_1_updated, point_2_updated; int poly_dx1, poly_dx2; int poly_x; @@ -300,6 +313,9 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p); static void s3_accel_out_w(uint16_t port, uint16_t val, void *p); static void s3_accel_out_l(uint16_t port, uint32_t val, void *p); static uint8_t s3_accel_in(uint16_t port, void *p); +static uint8_t s3_pci_read(int func, int addr, void *p); +static void s3_pci_write(int func, int addr, uint8_t val, void *p); + static __inline void wake_fifo_thread(s3_t *s3) @@ -322,10 +338,11 @@ s3_update_irqs(s3_t *s3) if (!s3->pci) return; - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { pci_set_irq(s3->card, PCI_INTA); - else + } 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); @@ -403,26 +420,24 @@ s3_data_len(s3_t *s3) static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { - svga_t *svga = &s3->svga; - if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + } else if (s3->accel.cmd & 0x400) s3_accel_start(32, 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 if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) + else if (s3->accel.cmd & 0x400) s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); else s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); @@ -432,18 +447,18 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) static void s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) -{ +{ if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { 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) { + } 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); @@ -459,9 +474,9 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) 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) { + 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 { @@ -474,9 +489,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) -{ - svga_t *svga = &s3->svga; - +{ switch (port) { case 0x8148: case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; @@ -594,11 +607,18 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.b2e8_pix = 0; break; case 0x9949: case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3_accel_start(-1, 0, 0xffffffff, 0, s3); s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ break; + case 0x994a: case 0x9aea: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff00) | val; + break; + case 0x994b: case 0x9aeb: + s3->accel.cmd2 = (s3->accel.cmd2 & 0xff) | (val << 8); + break; + case 0x9d48: case 0x9ee8: s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; @@ -802,6 +822,95 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; break; + case 0xd148: case 0xd2e8: + s3->accel.ropmix = (s3->accel.ropmix & 0xff00) | val; + break; + case 0xd149: case 0xd2e9: + s3->accel.ropmix = (s3->accel.ropmix & 0x00ff) | (val << 8); + break; + case 0xe548: case 0xe6e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + break; + case 0xe549: case 0xe6e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xe54a: case 0xe6ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x000000ff) | val; + } + break; + case 0xe54b: case 0xe6eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_bg_color = (s3->accel.pat_bg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe948: case 0xeae8: + s3->accel.pat_y = (s3->accel.pat_y & 0xf00) | val; + break; + case 0xe949: case 0xeae9: + s3->accel.pat_y = (s3->accel.pat_y & 0xff) | ((val & 0x1f) << 8); + break; + case 0xe94a: case 0xeaea: + s3->accel.pat_x = (s3->accel.pat_x & 0xf00) | val; + break; + case 0xe94b: case 0xeaeb: + s3->accel.pat_x = (s3->accel.pat_x & 0xff) | ((val & 0x1f) << 8); + break; + case 0xed48: case 0xeee8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + break; + case 0xed49: case 0xeee9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xed4a: case 0xeeea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x00ff0000) | (val << 16); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x000000ff) | val; + } + break; + case 0xed4b: case 0xeeeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0xff000000) | (val << 24); + else + s3->accel.pat_fg_color = (s3->accel.pat_fg_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; + case 0xe148: case 0xe2e8: s3->accel.b2e8_pix = 0; if (s3_cpu_dest(s3)) @@ -831,11 +940,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); } @@ -855,8 +963,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x400: - if (svga->crtc[0x53] & 0x08) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; } } @@ -887,7 +994,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) 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); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { 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); @@ -940,10 +1047,17 @@ static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { svga_t *svga = &s3->svga; - + if (s3->packed_mmio) { int addr_lo = addr & 1; - switch (addr & 0xfffe) { + if (svga->crtc[0x53] & 0x08) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + s3_pci_write(0, addr & 0xff, val, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + s3_out(addr & 0xfff, val, s3); + } + + switch (addr & 0x1fffe) { case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ case 0x8102: addr = 0x86e8; break; @@ -1019,12 +1133,25 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x814a: addr = 0x96e8; break; case 0x814c: addr = 0x96ea; break; + case 0x8150: addr = 0xd2e8; break; + + case 0x8154: addr = 0x8ee8; break; + case 0x8156: addr = 0x96e8; break; + + case 0x8164: case 0x8166: + WRITE8(addr, s3->accel.pat_bg_color, val); + return; + case 0x8168: addr = 0xeae8; break; case 0x816a: addr = 0xeaea; break; + + case 0x816c: case 0x816e: + WRITE8(addr, s3->accel.pat_fg_color, val); + return; } addr |= addr_lo; } - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xffff) < 0x8000) { if (s3->accel.cmd & 0x100) { @@ -1088,7 +1215,7 @@ static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { svga_t *svga = &s3->svga; - + if (svga->crtc[0x53] & 0x08) { if ((addr & 0xfffe) < 0x8000) { s3_accel_out_pixtrans_w(s3, val); @@ -1123,7 +1250,7 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) if ((addr & 0xfffc) < 0x8000) { s3_accel_out_pixtrans_l(s3, val); } else { - switch (addr & 0xfffc) { + switch (addr & 0xfffc) { case 0x8180: s3->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1254,13 +1381,16 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3_accel_write_fifo(s3, addr, val); break; + case 0x18080: + break; + default: 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); break; - } + } } } else { if (addr & 0x8000) { @@ -1732,7 +1862,7 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0x8d48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1745,7 +1875,11 @@ s3_io_remove_alt(s3_t *s3) io_removehandler(0xb548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } static void @@ -1775,7 +1909,11 @@ s3_io_remove(s3_t *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(0xd2e8, 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(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); s3_io_remove_alt(s3); } @@ -1783,13 +1921,18 @@ s3_io_remove(s3_t *s3) static void s3_io_set_alt(s3_t *s3) { + svga_t *svga = &s3->svga; + if (!s3->translate) return; + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x4948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { io_sethandler(0x8148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x8548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1807,7 +1950,10 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } - io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_VISION968) + io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9d48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1821,19 +1967,30 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xed48, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } } static void s3_io_set(s3_t *s3) { + svga_t *svga = &s3->svga; + s3_io_remove(s3); io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + return; + 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); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) { 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); @@ -1851,7 +2008,10 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) + io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + else + 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); @@ -1865,6 +2025,12 @@ s3_io_set(s3_t *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); + if (s3->chip == S3_VISION968) { + io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xeee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } s3_io_set_alt(s3); } @@ -1883,7 +2049,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) switch (addr) { case 0x3c2: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); } @@ -1906,6 +2072,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; + } else if (svga->seqaddr == 9) { + svga->seqregs[svga->seqaddr] = val & 0x80; + s3_io_set(s3); + return; + } else if (svga->seqaddr == 0xa) { + svga->seqregs[svga->seqaddr] = val & 0x80; + return; } break; @@ -1916,13 +2089,15 @@ s3_out(uint16_t addr, uint8_t val, void *p) rs2 = (svga->crtc[0x55] & 0x01); if (s3->chip >= S3_TRIO32) svga_out(addr, val, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { if (!(svga->crtc[0x45] & 0x20) || (s3->chip == S3_86C928)) rs3 = !!(svga->crtc[0x55] & 0x02); else rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + ibm_rgb525_ramdac_out(addr, rs2, val, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) att49x_ramdac_out(addr, val, svga->ramdac, svga); else if (s3->chip < S3_86C928) sc1148x_ramdac_out(addr, val, svga->ramdac, svga); @@ -1972,7 +2147,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) 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 0x80: s3->width = ((s3->chip > S3_86C805) && (s3->accel.advfunc_cntl & 4)) ? 1600 : 800; break; case 0x81: s3->width = 1600; break; case 0xc0: s3->width = 1280; break; } @@ -2020,13 +2195,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) break; case 0x45: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.ena = val & 1; break; case 0x46: case 0x47: case 0x48: case 0x49: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if (s3->chip == S3_VISION964) + if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; if (svga->bpp == 32) svga->hwcursor.x >>= 1; @@ -2073,6 +2248,9 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x53: case 0x58: case 0x59: case 0x5a: + if (svga->crtcreg == 0x59) + pclog("0x59 write val = %02x\n", val); + s3_updatemapping(s3); break; @@ -2088,8 +2266,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) } break; + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + break; + case 0x42: - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } @@ -2161,10 +2344,12 @@ s3_in(uint16_t addr, void *p) rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) return svga_in(addr, svga); - else if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) + return ibm_rgb525_ramdac_in(addr, rs2, svga->ramdac, svga); + else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) return att49x_ramdac_in(addr, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, svga->ramdac, svga); @@ -2186,18 +2371,24 @@ s3_in(uint16_t addr, void *p) 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 0x5c: /* General Output Port Register */ - temp = svga->crtc[svga->crtcreg] & 0xf0; - if (((svga->miscout >> 2) & 3) == 3) + temp = svga->crtc[svga->crtcreg] & 0xa0; + if (((svga->miscout >> 2) & 3) == 3) temp |= svga->crtc[0x42] & 0x0f; - else + else temp |= ((svga->miscout >> 2) & 3); - return temp; + if ((temp & 0xa0) == 0xa0) { + if ((svga->crtc[0x5c] & 0x40) && i2c_gpio_get_scl(s3->i2c)) + temp |= 0x40; + if ((svga->crtc[0x5c] & 0x10) && i2c_gpio_get_sda(s3->i2c)) + temp |= 0x10; + } + return temp; case 0x69: return s3->ma_ext; case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; - case 0x6c: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); + case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); } return svga->crtc[svga->crtcreg]; } @@ -2226,8 +2417,13 @@ static void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; - if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) - bt48x_recalctimings(svga->ramdac, svga); + if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { + if (s3->card_type == S3_ELSAWIN2KPROX_964) + ibm_rgb525_recalctimings(svga->ramdac, svga); + else + bt48x_recalctimings(svga->ramdac, svga); + } else if (s3->chip == S3_VISION968) + ibm_rgb525_recalctimings(svga->ramdac, svga); else svga->interlace = svga->crtc[0x42] & 0x20; @@ -2247,36 +2443,45 @@ static void s3_recalctimings(svga_t *svga) switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; + if (s3->width == 1280) + svga->hdisp *= 2; break; case 15: svga->render = svga_render_15bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 16: svga->render = svga_render_16bpp_highres; if ((s3->chip != S3_VISION964) && (s3->chip != S3_86C801)) { if (s3->chip == S3_86C928) svga->hdisp *= 2; - else + else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } + if (s3->width == 1280) + svga->hdisp *= 2; break; case 24: svga->render = svga_render_24bpp_highres; - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) + if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805 && s3->chip != S3_VISION968) svga->hdisp /= 3; else svga->hdisp = (svga->hdisp * 2) / 3; break; case 32: svga->render = svga_render_32bpp_highres; - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_86C928)) + if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && + (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) svga->hdisp /= 4; + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; break; } } @@ -2467,16 +2672,23 @@ s3_updatemapping(s3_t *s3) mem_mapping_disable(&s3->linear_mapping); if (!(svga->crtc[0x53] & 0x10)) { + pclog("Linear mapping enabled at 0xa0000\n"); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; } } else { + if (s3->chip >= S3_TRIO64V) + s3->linear_base &= 0xfc000000; + else + s3->linear_base &= 0xfe000000; + pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { + pclog("Linear mapping disabled\n"); mem_mapping_disable(&s3->linear_mapping); } - + /* Memory mapped I/O. */ if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) { mem_mapping_disable(&svga->mapping); @@ -2486,17 +2698,22 @@ s3_updatemapping(s3_t *s3) else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); } else { + pclog("Standard MMIO enabled at 0xa0000\n"); mem_mapping_enable(&s3->mmio_mapping); } } else { + pclog("Standard MMIO disabled\n"); mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { + pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); - } else - mem_mapping_disable(&s3->new_mmio_mapping); + } else { + pclog("New MMIO disabled\n", s3->linear_base); + mem_mapping_disable(&s3->new_mmio_mapping); + } } } @@ -2524,7 +2741,8 @@ s3_enable_fifo(s3_t *s3) if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || - (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964)) + (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || + (s3->chip == S3_VISION968)) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); @@ -2535,6 +2753,7 @@ static void s3_accel_out(uint16_t port, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; @@ -2564,6 +2783,11 @@ s3_accel_out(uint16_t port, uint8_t val, void *p) break; case 0x4948: case 0x4ae8: s3->accel.advfunc_cntl = val; + if ((s3->chip > S3_86C805) && ((svga->crtc[0x50] & 0xc1) == 0x80)) { + s3->width = (val & 4) ? 1600 : 800; + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } s3_updatemapping(s3); break; } @@ -2871,6 +3095,48 @@ s3_accel_in(uint16_t port, void *p) } break; + case 0xd148: case 0xd2e8: + return s3->accel.ropmix & 0xff; + + case 0xd149: case 0xd2e9: + return s3->accel.ropmix >> 8; + + case 0xe548: case 0xe6e8: + return s3->accel.pat_bg_color & 0xff; + + case 0xe549: case 0xe6e9: + return s3->accel.pat_bg_color >> 8; + + case 0xe54a: case 0xe6ea: + return s3->accel.pat_bg_color >> 16; + + case 0xe54b: case 0xe6eb: + return s3->accel.pat_bg_color >> 24; + + case 0xe948: case 0xeae8: + return s3->accel.pat_y & 0xff; + + case 0xe949: case 0xeae9: + return s3->accel.pat_y >> 8; + + case 0xe94a: case 0xeaea: + return s3->accel.pat_x & 0xff; + + case 0xe94b: case 0xeaeb: + return s3->accel.pat_x >> 8; + + case 0xed48: case 0xeee8: + return s3->accel.pat_fg_color & 0xff; + + case 0xed49: case 0xeee9: + return s3->accel.pat_fg_color >> 8; + + case 0xed4a: case 0xeeea: + return s3->accel.pat_fg_color >> 16; + + case 0xed4b: case 0xeeeb: + return s3->accel.pat_fg_color >> 24; + case 0xe148: case 0xe2e8: if (!s3_cpu_dest(s3)) break; @@ -2984,11 +3250,17 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) + if (!s3->enable_8514) { return 0xff; + } - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xffff) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + if ((addr >= 0x08000) && (addr <= 0x0803f)) + return s3_pci_read(0, addr & 0xff, s3); + else if ((addr >= 0x083b0) && (addr <= 0x083df)) + return s3_in(addr & 0xfff, s3); + + switch (addr & 0x1ffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: @@ -3006,6 +3278,9 @@ s3_accel_read(uint32_t addr, void *p) return s3->subsys_stat; case 0x8505: return s3->subsys_cntl; + /* Video engine status - currently a dummy. */ + case 0x1809c: case 0x1809d: case 0x1809e: case 0x1809f: + return 0x00; default: return s3_accel_in(addr & 0xffff, p); } @@ -3038,8 +3313,8 @@ s3_accel_read_w(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffe) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffe) { default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -3084,8 +3359,8 @@ s3_accel_read_l(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffffffff; - if (svga->crtc[0x53] & 0x08) { - switch (addr & 0xfffc) { + if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + switch (addr & 0x001fffc) { case 0x8180: temp = s3->streams.pri_ctrl; break; @@ -3241,6 +3516,7 @@ polygon_setup(s3_t *s3) } } + #define READ(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)]; @@ -3276,6 +3552,277 @@ polygon_setup(s3_t *s3) } + +#define ROPMIX_READ(D, P, S) \ + { \ + switch (rop) { \ + case 0x00: out = 0; break; \ + case 0x01: out = ~(D | (P | S)); break; \ + case 0x02: out = D & ~(P | S); break; \ + case 0x03: out = ~(P | S); break; \ + case 0x04: out = S & ~(D | P); break; \ + case 0x05: out = ~(D | P); break; \ + case 0x06: out = ~(P | ~(D ^ S)); break; \ + case 0x07: out = ~(P | (D & S)); break; \ + case 0x08: out = S & (D & ~P); break; \ + case 0x09: out = ~(P | (D ^ S)); break; \ + case 0x0a: out = D & ~P; break; \ + case 0x0b: out = ~(P | (S & ~D)); break; \ + case 0x0c: out = S & ~P; break; \ + case 0x0d: out = ~(P | (D & ~S)); break; \ + case 0x0e: out = ~(P | ~(D | S)); break; \ + case 0x0f: out = ~P; break; \ + case 0x10: out = P & ~(D | S); break; \ + case 0x11: out = ~(D | S); break; \ + case 0x12: out = ~(S | ~(D ^ P)); break; \ + case 0x13: out = ~(S | (D & P)); break; \ + case 0x14: out = ~(D | ~(P ^ S)); break; \ + case 0x15: out = ~(D | (P & S)); break; \ + case 0x16: out = P ^ (S ^ (D & ~(P & S))); break; \ + case 0x17: out = ~(S ^ ((S ^ P) & (D ^ S))); break; \ + case 0x18: out = (S ^ P) & (P ^ D); break; \ + case 0x19: out = ~(S ^ (D & ~(P & S))); break; \ + case 0x1a: out = P ^ (D | (S & P)); break; \ + case 0x1b: out = ~(S ^ (D & (P ^ S))); break; \ + case 0x1c: out = P ^ (S | (D & P)); break; \ + case 0x1d: out = ~(D ^ (S & (P ^ D))); break; \ + case 0x1e: out = P ^ (D | S); break; \ + case 0x1f: out = ~(P & (D | S)); break; \ + case 0x20: out = D & (P & ~S); break; \ + case 0x21: out = ~(S | (D ^ P)); break; \ + case 0x22: out = D & ~S; break; \ + case 0x23: out = ~(S | (P & ~D)); break; \ + case 0x24: out = (S ^ P) & (D ^ S); break; \ + case 0x25: out = ~(P ^ (D & ~(S & P))); break; \ + case 0x26: out = S ^ (D | (P & S)); break; \ + case 0x27: out = S ^ (D | ~(P ^ S)); break; \ + case 0x28: out = D & (P ^ S); break; \ + case 0x29: out = ~(P ^ (S ^ (D | (P & S)))); break; \ + case 0x2a: out = D & ~(P & S); break; \ + case 0x2b: out = ~(S ^ ((S ^ P) & (P ^ D))); break; \ + case 0x2c: out = S ^ (P & (D | S)); break; \ + case 0x2d: out = P ^ (S | ~D); break; \ + case 0x2e: out = P ^ (S | (D ^ P)); break; \ + case 0x2f: out = ~(P & (S | ~D)); break; \ + case 0x30: out = P & ~S; break; \ + case 0x31: out = ~(S | (D & ~P)); break; \ + case 0x32: out = S ^ (D | (P | S)); break; \ + case 0x33: out = ~S; break; \ + case 0x34: out = S ^ (P | (D & S)); break; \ + case 0x35: out = S ^ (P | ~(D ^ S)); break; \ + case 0x36: out = S ^ (D | P); break; \ + case 0x37: out = ~(S & (D | P)); break; \ + case 0x38: out = P ^ (S & (D | P)); break; \ + case 0x39: out = S ^ (P | ~D); break; \ + case 0x3a: out = S ^ (P | (D ^ S)); break; \ + case 0x3b: out = ~(S & (P | ~D)); break; \ + case 0x3c: out = P ^ S; break; \ + case 0x3d: out = S ^ (P | ~(D | S)); break; \ + case 0x3e: out = S ^ (P | (D & ~S)); break; \ + case 0x3f: out = ~(P & S); break; \ + case 0x40: out = P & (S & ~D); break; \ + case 0x41: out = ~(D | (P ^ S)); break; \ + case 0x42: out = (S ^ D) & (P ^ D); break; \ + case 0x43: out = ~(S ^ (P & ~(D & S))); break; \ + case 0x44: out = S & ~D; break; \ + case 0x45: out = ~(D | (P & ~S)); break; \ + case 0x46: out = D ^ (S | (P & D)); break; \ + case 0x47: out = ~(P ^ (S & (D ^ P))); break; \ + case 0x48: out = S & (D ^ P); break; \ + case 0x49: out = ~(P ^ (D ^ (S | (P & D)))); break; \ + case 0x4a: out = D ^ (P & (S | D)); break; \ + case 0x4b: out = P ^ (D | ~S); break; \ + case 0x4c: out = S & ~(D & P); break; \ + case 0x4d: out = ~(S ^ ((S ^ P) | (D ^ S))); break; \ + case 0x4e: out = P ^ (D | (S ^ P)); break; \ + case 0x4f: out = ~(P & (D | ~S)); break; \ + case 0x50: out = P & ~D; break; \ + case 0x51: out = ~(D | (S & ~P)); break; \ + case 0x52: out = D ^ (P | (S & D)); break; \ + case 0x53: out = ~(S ^ (P & (D ^ S))); break; \ + case 0x54: out = ~(D | ~(P | S)); break; \ + case 0x55: out = ~D; break; \ + case 0x56: out = D ^ (P | S); break; \ + case 0x57: out = ~(D & (P | S)); break; \ + case 0x58: out = P ^ (D & (S | P)); break; \ + case 0x59: out = D ^ (P | ~S); break; \ + case 0x5a: out = D ^ P; break; \ + case 0x5b: out = D ^ (P | ~(S | D)); break; \ + case 0x5c: out = D ^ (P | (S ^ D)); break; \ + case 0x5d: out = ~(D & (P | ~S)); break; \ + case 0x5e: out = D ^ (P | (S & ~D)); break; \ + case 0x5f: out = ~(D & P); break; \ + case 0x60: out = P & (D ^ S); break; \ + case 0x61: out = ~(D ^ (S ^ (P | (D & S)))); break; \ + case 0x62: out = D ^ (S & (P | D)); break; \ + case 0x63: out = S ^ (D | ~P); break; \ + case 0x64: out = S ^ (D & (P | S)); break; \ + case 0x65: out = D ^ (S | ~P); break; \ + case 0x66: out = D ^ S; break; \ + case 0x67: out = S ^ (D | ~(P | S)); break; \ + case 0x68: out = ~(D ^ (S ^ (P | ~(D | S)))); break; \ + case 0x69: out = ~(P ^ (D ^ S)); break; \ + case 0x6a: out = D ^ (P & S); break; \ + case 0x6b: out = ~(P ^ (S ^ (D & (P | S)))); break; \ + case 0x6c: out = S ^ (D & P); break; \ + case 0x6d: out = ~(P ^ (D ^ (S & (P | D)))); break; \ + case 0x6e: out = S ^ (D & (P | ~S)); break; \ + case 0x6f: out = ~(P & ~(D ^ S)); break; \ + case 0x70: out = P & ~(D & S); break; \ + case 0x71: out = ~(S ^ ((S ^ D) & (P ^ D))); break; \ + case 0x72: out = S ^ (D | (P ^ S)); break; \ + case 0x73: out = ~(S & (D | ~P)); break; \ + case 0x74: out = D ^ (S | (P ^ D)); break; \ + case 0x75: out = ~(D & (S | ~P)); break; \ + case 0x76: out = S ^ (D | (P & ~S)); break; \ + case 0x77: out = ~(D & S); break; \ + case 0x78: out = P ^ (D & S); break; \ + case 0x79: out = ~(D ^ (S ^ (P & (D | S)))); break; \ + case 0x7a: out = D ^ (P & (S | ~D)); break; \ + case 0x7b: out = ~(S & ~(D ^ P)); break; \ + case 0x7c: out = S ^ (P & (D | ~S)); break; \ + case 0x7d: out = ~(D & ~(P ^ S)); break; \ + case 0x7e: out = (S ^ P) | (D ^ S); break; \ + case 0x7f: out = ~(D & (P & S)); break; \ + case 0x80: out = D & (P & S); break; \ + case 0x81: out = ~((S ^ P) | (D ^ S)); break; \ + case 0x82: out = D & ~(P ^ S); break; \ + case 0x83: out = ~(S ^ (P & (D | ~S))); break; \ + case 0x84: out = S & ~(D ^ P); break; \ + case 0x85: out = ~(P ^ (D & (S | ~P))); break; \ + case 0x86: out = D ^ (S ^ (P & (D | S))); break; \ + case 0x87: out = ~(P ^ (D & S)); break; \ + case 0x88: out = D & S; break; \ + case 0x89: out = ~(S ^ (D | (P & ~S))); break; \ + case 0x8a: out = D & (S | ~P); break; \ + case 0x8b: out = ~(D ^ (S | (P ^ D))); break; \ + case 0x8c: out = S & (D | ~P); break; \ + case 0x8d: out = ~(S ^ (D | (P ^ S))); break; \ + case 0x8e: out = S ^ ((S ^ D) & (P ^ D)); break; \ + case 0x8f: out = ~(P & ~(D & S)); break; \ + case 0x90: out = P & ~(D ^ S); break; \ + case 0x91: out = ~(S ^ (D & (P | ~S))); break; \ + case 0x92: out = D ^ (P ^ (S & (D | P))); break; \ + case 0x93: out = ~(S ^ (P & D)); break; \ + case 0x94: out = P ^ (S ^ (D & (P | S))); break; \ + case 0x95: out = ~(D ^ (P & S)); break; \ + case 0x96: out = D ^ (P ^ S); break; \ + case 0x97: out = P ^ (S ^ (D | ~(P | S))); break; \ + case 0x98: out = ~(S ^ (D | ~(P | S))); break; \ + case 0x99: out = ~(D ^ S); break; \ + case 0x9a: out = D ^ (P & ~S); break; \ + case 0x9b: out = ~(S ^ (D & (P | S))); break; \ + case 0x9c: out = S ^ (P & ~D); break; \ + case 0x9d: out = ~(D ^ (S & (P | D))); break; \ + case 0x9e: out = D ^ (S ^ (P | (D & S))); break; \ + case 0x9f: out = ~(P & (D ^ S)); break; \ + case 0xa0: out = D & P; break; \ + case 0xa1: out = ~(P ^ (D | (S & ~P))); break; \ + case 0xa2: out = D & (P | ~S); break; \ + case 0xa3: out = ~(D ^ (P | (S ^ D))); break; \ + case 0xa4: out = ~(P ^ (D | ~(S | P))); break; \ + case 0xa5: out = ~(P ^ D); break; \ + case 0xa6: out = D ^ (S & ~P); break; \ + case 0xa7: out = ~(P ^ (D & (S | P))); break; \ + case 0xa8: out = D & (P | S); break; \ + case 0xa9: out = ~(D ^ (P | S)); break; \ + case 0xaa: out = D; break; \ + case 0xab: out = D | ~(P | S); break; \ + case 0xac: out = S ^ (P & (D ^ S)); break; \ + case 0xad: out = ~(D ^ (P | (S & D))); break; \ + case 0xae: out = D | (S & ~P); break; \ + case 0xaf: out = D | ~P; break; \ + case 0xb0: out = P & (D | ~S); break; \ + case 0xb1: out = ~(P ^ (D | (S ^ P))); break; \ + case 0xb2: out = S ^ ((S ^ P) | (D ^ S)); break; \ + case 0xb3: out = ~(S & ~(D & P)); break; \ + case 0xb4: out = P ^ (S & ~D); break; \ + case 0xb5: out = ~(D ^ (P & (S | D))); break; \ + case 0xb6: out = D ^ (P ^ (S | (D & P))); break; \ + case 0xb7: out = ~(S & (D ^ P)); break; \ + case 0xb8: out = P ^ (S & (D ^ P)); break; \ + case 0xb9: out = ~(D ^ (S | (P & D))); break; \ + case 0xba: out = D | (P & ~S); break; \ + case 0xbb: out = D | ~S; break; \ + case 0xbc: out = S ^ (P & ~(D & S)); break; \ + case 0xbd: out = ~((S ^ D) & (P ^ D)); break; \ + case 0xbe: out = D | (P ^ S); break; \ + case 0xbf: out = D | ~(P & S); break; \ + case 0xc0: out = P & S; break; \ + case 0xc1: out = ~(S ^ (P | (D & ~S))); break; \ + case 0xc2: out = ~(S ^ (P | ~(D | S))); break; \ + case 0xc3: out = ~(P ^ S); break; \ + case 0xc4: out = S & (P | ~D); break; \ + case 0xc5: out = ~(S ^ (P | (D ^ S))); break; \ + case 0xc6: out = S ^ (D & ~P); break; \ + case 0xc7: out = ~(P ^ (S & (D | P))); break; \ + case 0xc8: out = S & (D | P); break; \ + case 0xc9: out = ~(S ^ (P | D)); break; \ + case 0xca: out = D ^ (P & (S ^ D)); break; \ + case 0xcb: out = ~(S ^ (P | (D & S))); break; \ + case 0xcc: out = S; break; \ + case 0xcd: out = S | ~(D | P); break; \ + case 0xce: out = S | (D & ~P); break; \ + case 0xcf: out = S | ~P; break; \ + case 0xd0: out = P & (S | ~D); break; \ + case 0xd1: out = ~(P ^ (S | (D ^ P))); break; \ + case 0xd2: out = P ^ (D & ~S); break; \ + case 0xd3: out = ~(S ^ (P & (D | S))); break; \ + case 0xd4: out = S ^ ((S ^ P) & (P ^ D)); break; \ + case 0xd5: out = ~(D & ~(P & S)); break; \ + case 0xd6: out = P ^ (S ^ (D | (P & S))); break; \ + case 0xd7: out = ~(D & (P ^ S)); break; \ + case 0xd8: out = P ^ (D & (S ^ P)); break; \ + case 0xd9: out = ~(S ^ (D | (P & S))); break; \ + case 0xda: out = D ^ (P & ~(S & D)); break; \ + case 0xdb: out = ~((S ^ P) & (D ^ S)); break; \ + case 0xdc: out = S | (P & ~D); break; \ + case 0xdd: out = S | ~D; break; \ + case 0xde: out = S | (D ^ P); break; \ + case 0xdf: out = S | ~(D & P); break; \ + case 0xe0: out = P & (D | S); break; \ + case 0xe1: out = ~(P ^ (D | S)); break; \ + case 0xe2: out = D ^ (S & (P ^ D)); break; \ + case 0xe3: out = ~(P ^ (S | (D & P))); break; \ + case 0xe4: out = S ^ (D & (P ^ S)); break; \ + case 0xe5: out = ~(P ^ (D | (S & P))); break; \ + case 0xe6: out = S ^ (D & ~(P & S)); break; \ + case 0xe7: out = ~((S ^ P) & (P ^ D)); break; \ + case 0xe8: out = S ^ ((S ^ P) & (D ^ S)); break; \ + case 0xe9: out = ~(D ^ (S ^ (P & ~(D & S)))); break; \ + case 0xea: out = D | (P & S); break; \ + case 0xeb: out = D | ~(P ^ S); break; \ + case 0xec: out = S | (D & P); break; \ + case 0xed: out = S | ~(D ^ P); break; \ + case 0xee: out = D | S; break; \ + case 0xef: out = S | (D | ~P); break; \ + case 0xf0: out = P; break; \ + case 0xf1: out = P | ~(D | S); break; \ + case 0xf2: out = P | (D & ~S); break; \ + case 0xf3: out = P | ~S; break; \ + case 0xf4: out = P | (S & ~D); break; \ + case 0xf5: out = P | ~D; break; \ + case 0xf6: out = P | (D ^ S); break; \ + case 0xf7: out = P | ~(D & S); break; \ + case 0xf8: out = P | (D & S); break; \ + case 0xf9: out = P | ~(D ^ S); break; \ + case 0xfa: out = D | P; break; \ + case 0xfb: out = D | (P | ~S); break; \ + case 0xfc: out = P | S; break; \ + case 0xfd: out = P | (S | ~D); break; \ + case 0xfe: out = D | (P | S); break; \ + case 0xff: out = ~0; break; \ + } \ + } + + +#define ROPMIX { \ + old_dest_dat = dest_dat; \ + ROPMIX_READ(dest_dat, pat_dat, src_dat); \ + out = (out & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } + + #define WRITE(addr, dat) if (s3->bpp == 0) \ { \ svga->vram[(addr) & s3->vram_mask] = dat; \ @@ -3298,6 +3845,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { svga_t *svga = &s3->svga; uint32_t src_dat = 0, dest_dat, old_dest_dat; + uint32_t out, pat_dat = 0; int frgd_mix, bkgd_mix; int clip_t = s3->accel.multifunc[1] & 0xfff; int clip_l = s3->accel.multifunc[2] & 0xfff; @@ -3308,6 +3856,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ uint16_t *vram_w = (uint16_t *)svga->vram; uint32_t *vram_l = (uint32_t *)svga->vram; uint32_t compare = s3->accel.color_cmp; + uint8_t rop = s3->accel.ropmix & 0xff; int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; int cmd = s3->accel.cmd >> 13; @@ -3321,8 +3870,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((s3->chip >= S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968) && (s3->accel.cmd & (1 << 11))) { cmd |= 8; + } // SRC-BASE/DST-BASE if ((s3->accel.multifunc[0xd] >> 4) & 7) { @@ -3349,7 +3899,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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) { @@ -3377,7 +3927,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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 || s3->chip >= S3_TRIO64V) ? 0x80 : 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; @@ -3695,6 +4245,82 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } break; + + case 3: /*Polygon Fill Solid (Vision868/968 and Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + break; + + polygon_setup(s3); + + 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; + + 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 = dstbase + y * s3->width; + + while (x_count-- && count--) + { + if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && + (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= 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; /*Not supported?*/ break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + } + } + 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; + + case 6: /*BitBlt*/ if (!cpu_input) /*!cpu_input is trigger to start operation*/ { @@ -3725,7 +4351,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7) { - while (1) + while (count-- && s3->accel.sy >= 0) { if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) @@ -3971,86 +4597,112 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } break; - - case 3: /*Polygon Fill Solid (Trio64 only)*/ - { - int end_y1, end_y2; + + case 9: /*Polyline/2-Point Line (Vision868/968 and Trio64 only)*/ + { + int error; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; - polygon_setup(s3); + if (!cpu_input) { + s3->accel.dx = ABS(s3->accel.destx_distp - s3->accel.cur_x); + if (s3->accel.destx_distp & 0x1000) + s3->accel.dx |= ~0xfff; + s3->accel.dy = ABS(s3->accel.desty_axstp - s3->accel.cur_y); + if (s3->accel.desty_axstp & 0x1000) + s3->accel.dy |= ~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; + } 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; - - 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 = dstbase + y * s3->width; - - while (x_count-- && count--) - { - if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r && - (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b) + if (s3->accel.dx > s3->accel.dy) { + error = s3->accel.dx / 2; + while (s3->accel.cx != s3->accel.destx_distp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= 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; /*Not supported?*/ break; - } + src_dat = s3->accel.frgd_color; if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - READ(s3->accel.dest + s3->accel.poly_x, dest_dat); - + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + MIX - WRITE(s3->accel.dest + s3->accel.poly_x, dest_dat); + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } - 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++; + error -= s3->accel.dy; + if (error < 0) { + error += s3->accel.dx; + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + } + + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; else - s3->accel.poly_x--; + s3->accel.cx--; } - - 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; + } else { + error = s3->accel.dy / 2; + while (s3->accel.cy != s3->accel.desty_axstp && count--) { + if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && + (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) + { + src_dat = s3->accel.frgd_color; - case 11: /*Polygon Fill Pattern (Trio64 only)*/ + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + } + } + + error -= s3->accel.dx; + if (error < 0) { + error += s3->accel.dy; + if (s3->accel.destx_distp > s3->accel.cur_x) + s3->accel.cx++; + else + s3->accel.cx--; + } + if (s3->accel.desty_axstp > s3->accel.cur_y) + s3->accel.cy++; + else + s3->accel.cy--; + + } + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + + case 11: /*Polygon Fill Pattern (Vision868/968 and Trio64 only)*/ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) break; polygon_setup(s3); @@ -4133,6 +4785,144 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; } break; + + case 14: /*ROPBlt (Vision868/968 only)*/ + if (s3->chip != S3_VISION968) + break; + + 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.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.px = s3->accel.pat_x & 0xfff; + if (s3->accel.pat_x & 0x1000) s3->accel.px |= ~0xfff; + s3->accel.py = s3->accel.pat_y & 0xfff; + if (s3->accel.pat_y & 0x1000) s3->accel.py |= ~0xfff; + + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + } + + 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; + + while (count-- && s3->accel.sy >= 0) + { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && + (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= 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: READ(s3->accel.src + s3->accel.cx, src_dat); break; + } + + if (s3->accel.ropmix & 0x100) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.pat_bg_color; break; + case 1: pat_dat = s3->accel.pat_fg_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } else { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: pat_dat = s3->accel.bkgd_color; break; + case 1: pat_dat = s3->accel.frgd_color; break; + case 2: pat_dat = cpu_dat; break; + case 3: READ(s3->accel.pattern + s3->accel.px, pat_dat); break; + } + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ(s3->accel.dest + s3->accel.dx, dest_dat); + + ROPMIX + + WRITE(s3->accel.dest + s3->accel.dx, out); + } + } + + 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++; + s3->accel.px++; + } + else + { + s3->accel.cx--; + s3->accel.dx--; + s3->accel.px--; + } + 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; + s3->accel.px -= (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.px += (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++; + s3->accel.py++; + } + else + { + s3->accel.cy--; + s3->accel.dy--; + s3->accel.py--; + } + + s3->accel.src = srcbase + (s3->accel.cy * s3->width); + s3->accel.dest = dstbase + (s3->accel.dy * s3->width); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3->accel.sy--; + + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) { + return; + } + } + } + break; } } @@ -4150,7 +4940,11 @@ s3_pci_read(int func, int addr, void *p) case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; case PCI_REG_COMMAND: - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + if (s3->chip == S3_VISION968) + return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + else + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + break; case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ @@ -4158,13 +4952,13 @@ s3_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x00; /*Supports VGA interface*/ else return 0x01; break; case 0x0b: - if (s3->chip >= S3_TRIO32) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) return 0x03; else return 0x00; @@ -4172,8 +4966,8 @@ s3_pci_read(int func, int addr, void *p) case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return (s3->chip >= S3_TRIO64V) ? 0 : (svga->crtc[0x5a] & 0x80); - case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; + case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; @@ -4203,14 +4997,14 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x12: - if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2) { + if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968) { svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); } break; case 0x13: - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : val; + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968) ? (val & 0xfe) : val); s3_updatemapping(s3); break; @@ -4316,6 +5110,22 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); break; + case S3_ELSAWIN2KPROX_964: + bios_fn = ROM_ELSAWIN2KPROX_964; + chip = S3_VISION964; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); + break; + case S3_ELSAWIN2KPROX: + bios_fn = ROM_ELSAWIN2KPROX; + chip = S3_VISION968; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + break; case S3_PHOENIX_TRIO32: bios_fn = ROM_PHOENIX_TRIO32; chip = S3_TRIO32; @@ -4432,7 +5242,7 @@ static void *s3_init(const device_t *info) mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - if (chip == S3_VISION964) + if (chip == S3_VISION964 || chip == S3_VISION968) svga_init(info, &s3->svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, @@ -4456,8 +5266,10 @@ static void *s3_init(const device_t *info) svga->hwcursor.ysize = 64; - if (chip == S3_VISION964) + if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || chip == S3_VISION968) + svga->dac_hwcursor_draw = ibm_rgb525_hwcursor_draw; if (chip >= S3_VISION964) { switch (vram) { @@ -4489,13 +5301,20 @@ static void *s3_init(const device_t *info) break; } } - - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + + if (chip == S3_VISION968) { + if (s3->pci) + svga->crtc[0x36] = 2 | (0 << 2) | (1 << 4); + else + svga->crtc[0x36] = 1 | (0 << 2) | (1 << 4); + } else { + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); + } if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); @@ -4524,8 +5343,10 @@ static void *s3_init(const device_t *info) s3->fifo_thread = thread_create(fifo_thread, s3); s3->int_line = 0; + + s3->card_type = info->local; - switch(info->local) { + switch(s3->card_type) { case S3_ORCHID_86C911: case S3_DIAMOND_STEALTH_VRAM: svga->decode_mask = (1 << 20) - 1; @@ -4614,6 +5435,7 @@ static void *s3_init(const device_t *info) break; case S3_DIAMOND_STEALTH64_964: + case S3_ELSAWIN2KPROX_964: svga->decode_mask = (8 << 20) - 1; stepping = 0xd0; /*Vision964*/ s3->id = stepping; @@ -4621,10 +5443,33 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = device_add(&bt485_ramdac_device); + svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb525_ramdac_device) : device_add(&bt485_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - break; + break; + + case S3_ELSAWIN2KPROX: + svga->decode_mask = (8 << 20) - 1; + s3->id = 0xe1; /*Vision968*/ + s3->id_ext = 0xb0; + s3->id_ext_pci = 0xf0; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + svga->ramdac = device_add(&ibm_rgb525_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; case S3_PHOENIX_TRIO32: case S3_DIAMOND_STEALTH_SE: @@ -4723,6 +5568,16 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } +static int s3_elsa_winner2000_pro_x_964_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX_964); +} + +static int s3_elsa_winner2000_pro_x_available(void) +{ + return rom_present(ROM_ELSAWIN2KPROX); +} + static int s3_phoenix_trio32_available(void) { return rom_present(ROM_PHOENIX_TRIO32); @@ -4855,7 +5710,7 @@ static const device_config_t s3_phoenix_trio32_config[] = } }; -static const device_config_t s3_phoenix_trio64_onboard_config[] = +static const device_config_t s3_standard_config[] = { { "memory", "Video memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4879,7 +5734,7 @@ static const device_config_t s3_phoenix_trio64_onboard_config[] = } }; -static const device_config_t s3_config[] = +static const device_config_t s3_968_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 4, "", { 0 }, @@ -4987,7 +5842,7 @@ const device_t s3_metheus_86c928_isa_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_vlb_device = @@ -5001,7 +5856,7 @@ const device_t s3_metheus_86c928_vlb_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_metheus_86c928_pci_device = @@ -5015,7 +5870,7 @@ const device_t s3_metheus_86c928_pci_device = { s3_metheus_86c928_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_bahamas64_vlb_device = @@ -5057,7 +5912,7 @@ const device_t s3_diamond_stealth64_964_vlb_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_964_pci_device = @@ -5071,7 +5926,7 @@ const device_t s3_diamond_stealth64_964_pci_device = { s3_diamond_stealth64_964_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_9fx_vlb_device = @@ -5170,7 +6025,7 @@ const device_t s3_phoenix_trio64_vlb_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64_onboard_pci_device = @@ -5184,7 +6039,7 @@ const device_t s3_phoenix_trio64_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64_pci_device = @@ -5198,7 +6053,7 @@ const device_t s3_phoenix_trio64_pci_device = { s3_phoenix_trio64_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_vlb_device = @@ -5212,7 +6067,7 @@ const device_t s3_phoenix_trio64vplus_vlb_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_onboard_pci_device = @@ -5226,7 +6081,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = { NULL }, s3_speed_changed, s3_force_redraw, - s3_phoenix_trio64_onboard_config + s3_standard_config }; const device_t s3_phoenix_trio64vplus_pci_device = @@ -5240,7 +6095,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = { s3_phoenix_trio64vplus_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_vlb_device = @@ -5254,7 +6109,7 @@ const device_t s3_phoenix_vision864_vlb_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_phoenix_vision864_pci_device = @@ -5268,7 +6123,7 @@ const device_t s3_phoenix_vision864_pci_device = { s3_phoenix_vision864_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; const device_t s3_diamond_stealth64_vlb_device = @@ -5299,6 +6154,63 @@ const device_t s3_diamond_stealth64_pci_device = s3_9fx_config }; +const device_t s3_elsa_winner2000_pro_x_964_pci_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_964_vlb_device = +{ + "S3 Vision964 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX_964, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_964_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_pci_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) PCI", + DEVICE_PCI, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + +const device_t s3_elsa_winner2000_pro_x_vlb_device = +{ + "S3 Vision968 (ELSA Winner 2000 Pro/X) VLB", + DEVICE_VLB, + S3_ELSAWIN2KPROX, + s3_init, + s3_close, + NULL, + { s3_elsa_winner2000_pro_x_available }, + s3_speed_changed, + s3_force_redraw, + s3_968_config +}; + + const device_t s3_trio64v2_dx_pci_device = { "S3 Trio64V2/DX PCI", @@ -5310,5 +6222,6 @@ const device_t s3_trio64v2_dx_pci_device = { s3_trio64v2_dx_available }, s3_speed_changed, s3_force_redraw, - s3_config + s3_standard_config }; + diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d675ab322..88304b797 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -129,6 +129,8 @@ video_cards[] = { { "stealth3d_3000_pci", &s3_virge_988_pci_device }, { "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "elsawin2kprox_964_pci", &s3_elsa_winner2000_pro_x_964_pci_device }, + { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, { "stealthse_pci", &s3_diamond_stealth_se_pci_device }, #if defined(DEV_BRANCH) && defined(USE_MGA) { "mystique", &mystique_device }, @@ -165,6 +167,8 @@ video_cards[] = { { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, + { "elsawin2kprox_964_vlb", &s3_elsa_winner2000_pro_x_964_vlb_device }, + { "elsawin2kprox_vlb", &s3_elsa_winner2000_pro_x_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, { "n9_9fx_vlb", &s3_9fx_vlb_device }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index c7cba0b80..9cf52250d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -742,7 +742,7 @@ VIDOBJ := video.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ vid_s3.o vid_s3_virge.o \ - vid_sdac_ramdac.o \ + vid_ibm_rgb525_ramdac.o vid_sdac_ramdac.o \ vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o \ From 13689ca958fa86d8d29f863d839bdb8182a6292a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Dec 2020 13:23:37 +0100 Subject: [PATCH 15/60] Fixed the new MMIO mapping size of the S3 Virge968, Paintbrush no longer hangs but does not display correctly, pending the implementation of the Video engine. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index dafd25ebc..8e2523bbb 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2709,7 +2709,7 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x10000); + mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { pclog("New MMIO disabled\n", s3->linear_base); mem_mapping_disable(&s3->new_mmio_mapping); From a00b82cdf8ee959761c29afba5f36ea604804dc0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 15 Dec 2020 19:51:48 +0100 Subject: [PATCH 16/60] Fixed S3 linear mapping on Vision964 and earlier. --- src/video/vid_s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8e2523bbb..7f310a2d1 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2679,7 +2679,7 @@ s3_updatemapping(s3_t *s3) } else { if (s3->chip >= S3_TRIO64V) s3->linear_base &= 0xfc000000; - else + else if (s3->chip == S3_VISION968) s3->linear_base &= 0xfe000000; pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); From fd044440b3be0b14487b046b933a3a11c3eaca18 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 8 Dec 2020 22:56:45 +0100 Subject: [PATCH 17/60] S3 Vision968 work. --- src/video/vid_s3.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7f310a2d1..0034ce843 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2681,7 +2681,6 @@ s3_updatemapping(s3_t *s3) s3->linear_base &= 0xfc000000; else if (s3->chip == S3_VISION968) s3->linear_base &= 0xfe000000; - pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { @@ -2708,7 +2707,6 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { - pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { pclog("New MMIO disabled\n", s3->linear_base); From 7733bc826d9c8fe5abb99d55b9af41d269b12c86 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 9 Dec 2020 13:23:37 +0100 Subject: [PATCH 18/60] Fixed the new MMIO mapping size of the S3 Virge968, Paintbrush no longer hangs but does not display correctly, pending the implementation of the Video engine. --- src/video/vid_s3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 0034ce843..5ed6236ad 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2707,6 +2707,7 @@ s3_updatemapping(s3_t *s3) /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { + pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { pclog("New MMIO disabled\n", s3->linear_base); From 51009d8e2850b1ffa158f7a648cfc5732361b04a Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Sat, 19 Dec 2020 21:17:11 +0100 Subject: [PATCH 19/60] Added the following new machines: - Multitech pc-700 - Philips P3105/NMS9100 - Philips P3120 --- src/include/86box/machine.h | 3 ++ src/machine/m_xt.c | 74 +++++++++++++++++++++++++++++++++++++ src/machine/machine_table.c | 3 ++ 3 files changed, 80 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 25811a9c6..e2dc4aee6 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -584,6 +584,9 @@ extern int machine_xt_pxxt_init(const machine_t *); extern int machine_xt_ncrpc4i_init(const machine_t *); extern int machine_xt_mpc1600_init(const machine_t *); extern int machine_xt_eaglepcspirit_init(const machine_t *); +extern int machine_xt_multitechpc700_init(const machine_t *); +extern int machine_xt_p3105_init(const machine_t *); +extern int machine_xt_p3120_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index c5c1acc1c..7640b0932 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -378,5 +378,79 @@ machine_xt_eaglepcspirit_init(const machine_t *model) machine_xt_common_init(model); + return ret; +} + +int +machine_xt_multitechpc700_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/multitech_pc700/multitech pc-700 3.1.bin", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_xt_common_init(model); + + return ret; +} + + +/* + * Current bugs and limitations: + * - 640-768 conventional memory not usable (should be mapped at address d0000-effff) + */ +int +machine_xt_p3105_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/philips_p3105/philipsnms9100.bin", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_xt_common_init(model); + + return ret; +} + +/* + * Current bugs and limitations: + * - 640-768 conventional memory not usable (should be mapped at address d0000-effff) + * - BIOS detects 4 fdds, so hdd letter is E instead of C + */ +int +machine_xt_p3120_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/philips_p3120/philips_p3120.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_common_init(model); + + pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + nmi_init(); + + if (joystick_type) + device_add(&gameport_device); + return ret; } \ No newline at end of file diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 5504b69a3..1ff1b99ee 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -69,9 +69,12 @@ const machine_t machines[] = { { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, + { "[8088] Multitech PC-700", "multitech_pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc700_init, NULL }, { "[8088] NCR PC4i", "ncr_pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_ncrpc4i_init, NULL }, { "[8088] Olivetti M19", "olivetti_m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_olim19_init, NULL }, { "[8088] OpenXT", "open_xt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_open_xt_init, NULL }, + { "[8088] Philips P3105/NMS9100", "philips_p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, + { "[8088] Philips P3120", "philips_p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3120_init, NULL }, { "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, { "[8088] Schneider EuroPC", "europc", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, { "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, From da1de8aaf57edece4b0ebb1477b46ef78bbc17ed Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 20 Dec 2020 21:14:24 +0100 Subject: [PATCH 20/60] 40x25 text mode and Cardex ET4000/w32p 80x25 text mode now actually fixes. --- src/video/vid_et4000w32.c | 11 +++++++++++ src/video/vid_svga.c | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index b3eb235bd..e856c9675 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -355,6 +355,17 @@ void et4000w32p_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double)(1ull << 32)) / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + if (svga->adv_flags & FLAG_NOSKEW) { + /* On the Cardex ET4000/W32p, adjust text mode clocks by 1. */ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->ma_latch--; + if ((svga->seqregs[1] & 8)) /*40 column*/ + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; + else + svga->hdisp += (svga->seqregs[1] & 1) ? 8 : 9; + } + } + switch (svga->bpp) { case 15: case 16: diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 0298c3f36..61dcc6d1f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -445,7 +445,7 @@ svga_recalctimings(svga_t *svga) svga->interlace = 0; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]); + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); svga->ca_adj = 0; svga->rowcount = svga->crtc[9] & 31; @@ -457,10 +457,11 @@ svga_recalctimings(svga_t *svga) if (svga->seqregs[1] & 8) /*40 column*/ { svga->render = svga_render_text_40; svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + /* Character clock is off by 1 now in 40-line modes, on all cards. */ + svga->ma_latch--; + svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18; } else { svga->render = svga_render_text_80; - if (!(svga->adv_flags & FLAG_NOSKEW)) - svga->ma_latch += ((svga->crtc[8] & 0x60) >> 5); svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; } svga->hdisp_old = svga->hdisp; From 978f02aa99d968a770a45b3737f6304fc997369a Mon Sep 17 00:00:00 2001 From: Winins0 <65453129+Winins0@users.noreply.github.com> Date: Mon, 21 Dec 2020 19:49:08 +0300 Subject: [PATCH 21/60] Gave 1.x/2.0 Sound Blasters port 0x260. (#1185) --- src/sound/snd_sb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 353d25987..303c69ba1 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1506,8 +1506,11 @@ static const device_config_t sb_config[] = "0x240", 0x240 }, { - "" - } + "0x260", 0x260 + }, + { + "" + } } }, { From b44ba0e69bd5399eec5f15ff783836e1be49cc3d Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 21 Dec 2020 20:53:24 +0100 Subject: [PATCH 22/60] Fixed the previous commit. --- src/sound/snd_ad1848.c | 2 +- src/video/vid_voodoo_banshee.c | 91 ++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index be11e09ca..fc859f8cc 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -299,6 +299,6 @@ void ad1848_init(ad1848_t *ad1848, int type) timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0); - if (ad1848->type != AD1848_TYPE_DEFAULT) + if (ad1848->type != AD1848_TYPE_DEFAULT && ad1848->type != AD1848_TYPE_CS4248) sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848); } diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 7401df0d0..b749e0cf2 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -116,7 +116,8 @@ typedef struct banshee_t int desktop_y; uint32_t desktop_stride_tiled; - int type; + int type, card; + int vblank_irq; void *i2c, *i2c_ddc, *ddc; } banshee_t; @@ -179,6 +180,7 @@ enum #define VGAINIT0_EXTENDED_SHIFT_OUT (1 << 12) #define VIDPROCCFG_CURSOR_MODE (1 << 1) +#define VIDPROCCFG_INTERLACE (1 << 3) #define VIDPROCCFG_HALF_MODE (1 << 4) #define VIDPROCCFG_OVERLAY_ENABLE (1 << 8) #define VIDPROCCFG_OVERLAY_CLUT_BYPASS (1 << 11) @@ -256,6 +258,32 @@ banshee_log(const char *fmt, ...) static uint32_t banshee_status(banshee_t *banshee); +static int banshee_vga_vsync_enabled(banshee_t *banshee) +{ + if (!(banshee->svga.crtc[0x11] & 0x20) && (banshee->svga.crtc[0x11] & 0x10) && ((banshee->pciInit0 >> 18) & 1) != 0) + return 1; + return 0; +} + +static void banshee_update_irqs(banshee_t *banshee) +{ + if (banshee->vblank_irq > 0 && banshee_vga_vsync_enabled(banshee)) { + pci_set_irq(banshee->card, PCI_INTA); + } else { + pci_clear_irq(banshee->card, PCI_INTA); + } +} + +static void banshee_vblank_start(svga_t* svga) +{ + banshee_t *banshee = (banshee_t*)svga->p; + if (banshee->vblank_irq >= 0) { + banshee->vblank_irq = 1; + banshee_update_irqs(banshee); + } +} + + static void banshee_out(uint16_t addr, uint8_t val, void *p) { banshee_t *banshee = (banshee_t *)p; @@ -281,7 +309,18 @@ static void banshee_out(uint16_t addr, uint8_t val, void *p) svga->crtc[svga->crtcreg] = val; if (old != val) { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + if (svga->crtcreg == 0x11) { + if (!(val & 0x10)) { + if (banshee->vblank_irq > 0) + banshee->vblank_irq = -1; + } else if (banshee->vblank_irq < 0) { + banshee->vblank_irq = 0; + } + banshee_update_irqs(banshee); + if ((val & ~0x30) == (old & ~0x30)) + old = val; + } + if (svga->crtcreg < 0xe || svga->crtcreg > 0x11 || (svga->crtcreg == 0x11 && old != val)) { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -310,6 +349,8 @@ static uint8_t banshee_in(uint16_t addr, void *p) temp = 0; else temp = 0x10; + if (banshee->vblank_irq > 0) + temp |= 0x80; break; case 0x3D4: temp = svga->crtcreg; @@ -440,6 +481,8 @@ static void banshee_recalctimings(svga_t *svga) if (svga->crtc[0x1b] & 0x40) svga->vsyncstart += 0x400; // banshee_log("svga->hdisp=%i\n", svga->hdisp); + svga->interlace = 0; + if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) { switch (VIDPROCCFG_DESKTOP_PIX_FORMAT) @@ -484,6 +527,8 @@ static void banshee_recalctimings(svga_t *svga) svga->htotal *= 2; } + svga->interlace = !!(banshee->vidProcCfg & VIDPROCCFG_INTERLACE); + svga->overlay.ena = banshee->vidProcCfg & VIDPROCCFG_OVERLAY_ENABLE; svga->overlay.x = voodoo->overlay.start_x; @@ -791,7 +836,6 @@ static uint32_t banshee_status(banshee_t *banshee) voodoo_t *voodoo = banshee->voodoo; svga_t *svga = &banshee->svga; int fifo_entries = FIFO_ENTRIES; - int fifo_size = 0xffff - fifo_entries; int swap_count = voodoo->swap_count; int written = voodoo->cmd_written + voodoo->cmd_written_fifo; int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) || @@ -801,11 +845,11 @@ static uint32_t banshee_status(banshee_t *banshee) uint32_t ret; ret = 0; - if (fifo_size < 0x20) - ret |= fifo_size; + if (fifo_entries < 0x20) + ret |= 0x1f - fifo_entries; else ret |= 0x1f; - if (fifo_size) + if (fifo_entries) ret |= 0x20; if (swap_count < 7) ret |= (swap_count << 28); @@ -1041,6 +1085,14 @@ static uint32_t banshee_reg_readl(uint32_t addr, void *p) voodoo_flush(voodoo); switch (addr & 0x1fc) { + case SST_status: + ret = banshee_status(banshee); + break; + + case SST_intrCtrl: + ret = banshee->intrCtrl & 0x0030003f; + break; + case 0x08: ret = voodoo->banshee_blt.clip0Min; break; @@ -1271,7 +1323,11 @@ static void banshee_reg_writel(uint32_t addr, uint32_t val, void *p) break; case 0x0100000: /*2D registers*/ - voodoo_queue_command(voodoo, (addr & 0x1fc) | FIFO_WRITEL_2DREG, val); + if ((addr & 0x3fc) == SST_intrCtrl) { + banshee->intrCtrl = val & 0x0030003f; + } else { + voodoo_queue_command(voodoo, (addr & 0x1fc) | FIFO_WRITEL_2DREG, val); + } break; case 0x0200000: case 0x0300000: case 0x0400000: case 0x0500000: /*3D registers*/ @@ -2365,8 +2421,8 @@ static uint8_t banshee_pci_read(int func, int addr, void *p) case 0x18: ret = 0x01; break; /*ioBaseAddr*/ case 0x19: ret = banshee->ioBaseAddr >> 8; break; - case 0x1a: ret = 0x00; break; - case 0x1b: ret = 0x00; break; + case 0x1a: ret = banshee->ioBaseAddr >> 16; break; + case 0x1b: ret = banshee->ioBaseAddr >> 24; break; /*Subsystem vendor ID*/ case 0x2c: ret = banshee->pci_regs[0x2c]; break; @@ -2445,12 +2501,23 @@ static void banshee_pci_write(int func, int addr, uint8_t val, void *p) case 0x19: if (banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); - banshee->ioBaseAddr = val << 8; + banshee->ioBaseAddr &= 0xffff00ff; + banshee->ioBaseAddr |= val << 8; if ((banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && banshee->ioBaseAddr) io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee); banshee_log("Banshee ioBaseAddr=%08x\n", banshee->ioBaseAddr); return; + case 0x1a: + banshee->ioBaseAddr &= 0xff00ffff; + banshee->ioBaseAddr |= val << 16; + break; + + case 0x1b: + banshee->ioBaseAddr &= 0x00ffffff; + banshee->ioBaseAddr |= val << 24; + break; + case 0x30: case 0x32: case 0x33: banshee->pci_regs[addr] = val; if (banshee->pci_regs[0x30] & 0x01) @@ -2645,6 +2712,8 @@ static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgra MEM_MAPPING_EXTERNAL, banshee); + banshee->svga.vblank_start = banshee_vblank_start; + // io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee); banshee->svga.bpp = 8; @@ -2657,7 +2726,7 @@ static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgra banshee->dramInit1 = 1 << 30; /*SDRAM*/ banshee->svga.decode_mask = 0x1ffffff; - pci_add_card(PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); + banshee->card = pci_add_card(PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); banshee->voodoo = voodoo_2d3d_card_init(voodoo_type); banshee->voodoo->p = banshee; From 4b42251b846578f1e163a749a92328c88b61b22d Mon Sep 17 00:00:00 2001 From: luisjoseromero Date: Tue, 22 Dec 2020 00:19:45 +0000 Subject: [PATCH 23/60] Fix blit thread related deadlocks Removed unnecessary calls to video_wait_for_blit(), which in addition to not doing much were also in a race with the video_blit_memtoscreen() thread to wait for and reset the blit_data.blit_complete event signalled by blit_thread(), causing several deadlocks. --- src/win/win.c | 4 ---- src/win/win_ui.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index 5322d6c55..74f8d16a4 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -719,7 +719,6 @@ plat_setvid(int api) win_log("Initializing VIDAPI: api=%d\n", api); startblit(); - video_wait_for_blit(); /* Close the (old) API. */ vid_apis[vid_api].close(); @@ -750,7 +749,6 @@ plat_vidsize(int x, int y) if (!vid_api_inited || !vid_apis[vid_api].resize) return; startblit(); - video_wait_for_blit(); vid_apis[vid_api].resize(x, y); endblit(); } @@ -764,7 +762,6 @@ plat_vidapi_enable(int enable) if (!vid_api_inited || !vid_apis[vid_api].enable) return; - video_wait_for_blit(); vid_apis[vid_api].enable(enable != 0); if (! i) @@ -803,7 +800,6 @@ plat_setfullscreen(int on) } /* OK, claim the video. */ - video_wait_for_blit(); win_mouse_close(); /* Close the current mode, and open the new one. */ diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 0cc399117..2b8623ce2 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -166,7 +166,6 @@ static void video_toggle_option(HMENU h, int *val, int id) { startblit(); - video_wait_for_blit(); *val ^= 1; CheckMenuItem(h, id, *val ? MF_CHECKED : MF_UNCHECKED); endblit(); @@ -1467,8 +1466,6 @@ plat_resize(int x, int y) /* First, see if we should resize the UI window. */ if (!vid_resize) { - video_wait_for_blit(); - /* scale the screen base on DPI */ if (dpi_scale) { From eeabeeb2bb2946b14f0a4a690774c792a5a67cfd Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 22 Dec 2020 14:17:22 +0100 Subject: [PATCH 24/60] Added the latest fixes to support the 868/968 video engine and the 868 itself. --- src/include/86box/video.h | 2 + src/video/vid_s3.c | 757 ++++++++++++++++++++++++++++++++------ src/video/vid_table.c | 2 + 3 files changed, 658 insertions(+), 103 deletions(-) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 2079265c2..b7c356942 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -324,6 +324,8 @@ extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; +extern const device_t s3_phoenix_vision868_pci_device; +extern const device_t s3_phoenix_vision868_vlb_device; extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 9efd728e2..1ccf928a0 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include <86box/86box.h> #include <86box/device.h> @@ -54,6 +55,7 @@ #define ROM_DIAMOND_STEALTH_SE L"roms/video/s3/DiamondStealthSE.VBI" #define ROM_ELSAWIN2KPROX_964 L"roms/video/s3/elsaw20004m.BIN" #define ROM_ELSAWIN2KPROX L"roms/video/s3/elsaw20008m.BIN" +#define ROM_PHOENIX_VISION868 L"roms/video/s3/1-DSV3868.BIN" enum { @@ -76,7 +78,8 @@ enum S3_DIAMOND_STEALTH_SE, S3_DIAMOND_STEALTH_VRAM, S3_ELSAWIN2KPROX_964, - S3_ELSAWIN2KPROX + S3_ELSAWIN2KPROX, + S3_PHOENIX_VISION868 }; @@ -90,10 +93,11 @@ enum S3_VISION964 = 0x08, S3_VISION968 = 0x10, S3_VISION864 = 0x18, - S3_TRIO32 = 0x20, - S3_TRIO64 = 0x28, - S3_TRIO64V = 0x30, - S3_TRIO64V2 = 0x38 + S3_VISION868 = 0x20, + S3_TRIO32 = 0x28, + S3_TRIO64 = 0x30, + S3_TRIO64V = 0x38, + S3_TRIO64V2 = 0x40 }; @@ -104,6 +108,8 @@ static video_timings_t timing_s3_stealth64_vlb = {VIDEO_BUS, 2, 2, 4, 26, 26, static video_timings_t timing_s3_stealth64_pci = {VIDEO_PCI, 2, 2, 4, 26, 26, 42}; static video_timings_t timing_s3_vision864_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_vision864_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; +static video_timings_t timing_s3_vision868_vlb = {VIDEO_BUS, 4, 4, 5, 20, 20, 35}; +static video_timings_t timing_s3_vision868_pci = {VIDEO_PCI, 4, 4, 5, 20, 20, 35}; static video_timings_t timing_s3_vision964_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_vision964_pci = {VIDEO_PCI, 2, 2, 4, 20, 20, 35}; static video_timings_t timing_s3_vision968_vlb = {VIDEO_BUS, 2, 2, 4, 20, 20, 35}; @@ -230,6 +236,36 @@ typedef struct s3_t int b2e8_pix, temp_cnt; } accel; + struct { + uint32_t nop; + uint32_t cntl; + uint32_t stretch_filt_const; + uint32_t src_dst_step; + uint32_t crop; + uint32_t src_base, dest_base; + uint32_t src, dest; + uint32_t srcbase, dstbase; + int32_t dda_init_accumulator; + int32_t k1, k2; + int dm_index; + int dither_matrix_idx; + int src_step, dst_step; + int sx, sx_backup, sy; + double cx, dx; + double cy, dy; + int sx_scale_int, sx_scale_int_backup; + double sx_scale; + double sx_scale_dec; + double sx_scale_inc; + double sx_scale_backup; + double sx_scale_len; + int dither, host_data, scale_down; + int input; + int len, start; + int odf, idf, yuv; + volatile int busy; + } videoengine; + struct { uint32_t pri_ctrl; @@ -346,6 +382,7 @@ s3_update_irqs(s3_t *s3) } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); +static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) switch ((addr) & 3) \ { \ @@ -420,17 +457,19 @@ s3_data_len(s3_t *s3) static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { + svga_t *svga = &s3->svga; + if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { if (s3->accel.cmd & 0x1000) val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { 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 if (s3->accel.cmd & 0x400) + } else if ((s3->accel.cmd & 0x400) && (svga->crtc[0x53] & 0x08)) s3_accel_start(32, 1, val | (val << 16), 0, s3); else s3_accel_start(16, 1, val | (val << 16), 0, s3); @@ -451,7 +490,7 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) { - if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V)) { + if ((s3->accel.cmd & 0x600) == 0x600 && (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V)) { 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); @@ -490,6 +529,8 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { + svga_t *svga = &s3->svga; + switch (port) { case 0x8148: case 0x82e8: s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; @@ -940,7 +981,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x400: - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (svga->crtc[0x53] & 0x08) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { @@ -963,7 +1005,8 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x400: - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + if (svga->crtc[0x53] & 0x08) + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; } } @@ -1053,8 +1096,6 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) if (svga->crtc[0x53] & 0x08) { if ((addr >= 0x08000) && (addr <= 0x0803f)) s3_pci_write(0, addr & 0xff, val, s3); - else if ((addr >= 0x083b0) && (addr <= 0x083df)) - s3_out(addr & 0xfff, val, s3); } switch (addr & 0x1fffe) { @@ -1153,7 +1194,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) } if (svga->crtc[0x53] & 0x08) { - if ((addr & 0xffff) < 0x8000) { + if ((addr & 0x1ffff) < 0x8000) { if (s3->accel.cmd & 0x100) { if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); @@ -1161,7 +1202,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { - switch (addr & 0xffff) { + switch (addr & 0x1ffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb: @@ -1217,10 +1258,10 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) svga_t *svga = &s3->svga; if (svga->crtc[0x53] & 0x08) { - if ((addr & 0xfffe) < 0x8000) { + if ((addr & 0x1fffe) < 0x8000) { s3_accel_out_pixtrans_w(s3, val); } else { - switch (addr & 0xfffe) { + switch (addr & 0x1fffe) { case 0x83d4: default: s3_accel_write_fifo(s3, addr, val); @@ -1247,10 +1288,14 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) svga_t *svga = &s3->svga; if (svga->crtc[0x53] & 0x08) { - if ((addr & 0xfffc) < 0x8000) { - s3_accel_out_pixtrans_l(s3, val); + if ((addr & 0x1fffc) < 0x8000 || ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000)) { + if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { + s3_visionx68_video_engine_op(val, s3); + } else if ((addr & 0x1fffc) < 0x8000) { + s3_accel_out_pixtrans_l(s3, val); + } } else { - switch (addr & 0xfffc) { + switch (addr & 0x1fffc) { case 0x8180: s3->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1382,8 +1427,53 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) break; case 0x18080: + s3->videoengine.nop = 1; + //pclog("Video Engine NOP\n"); break; + case 0x18088: + s3->videoengine.cntl = val; + s3->videoengine.dda_init_accumulator = val & 0xfff; + s3->videoengine.odf = (val >> 16) & 7; + s3->videoengine.yuv = !!(val & (1 << 19)); + s3->videoengine.idf = (val >> 20) & 7; + s3->videoengine.dither = !!(val & (1 << 29)); + s3->videoengine.dm_index = (val >> 23) & 7; + //pclog("Video Engine cntl write = %08x, dda init acc = %08x, ODF = %i, IDF = %i, Key Mask = %i, OTT = %i\n", val, s3->videoengine.dda_init_accumulator, s3->videoengine.odf, s3->videoengine.idf, !!(val & (1 << 26)), !!(val & (1 << 28))); + break; + + case 0x1808c: + s3->videoengine.stretch_filt_const = val; + s3->videoengine.k2 = val & 0x7ff; + s3->videoengine.k1 = (val >> 16) & 0x7ff; + s3->videoengine.host_data = !!(val & (1 << 30)); + s3->videoengine.scale_down = !!(val & (1 << 31)); + //pclog("Video Engine stretch/filter constants write = %08x, k2 = %08x, k1 = %08x, host data = %i, down = %i, sense = %i\n", val, s3->videoengine.k2, s3->videoengine.k1, !!(val & (1 << 30)), !!(val & (1 << 31)), !!(val & (1 << 29))); + break; + + case 0x18090: + s3->videoengine.src_dst_step = val; + s3->videoengine.dst_step = val & 0x1fff; + s3->videoengine.src_step = (val >> 16) & 0x1fff; + //pclog("Video Engine SRC/DST Step val = %08x, SRCStep = %i, DSTStep = %i\n", val, s3->videoengine.src_step, s3->videoengine.dst_step); + break; + + case 0x18094: + s3->videoengine.crop = val; + s3->videoengine.len = val & 0xfff; + s3->videoengine.start = (val >> 16) & 0xfff; + s3->videoengine.input = 1; + //pclog("Video Engine Crop val = %08x, Length = %i, Start = %i\n", val, s3->videoengine.len, s3->videoengine.start); + break; + + case 0x18098: + s3->videoengine.src_base = val & 0xffffff; + break; + + case 0x1809c: + s3->videoengine.dest_base = val & 0xffffff; + break; + default: s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); @@ -1804,6 +1894,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) } \ } while (0) + static void s3_trio64v_overlay_draw(svga_t *svga, int displine) { s3_t *s3 = (s3_t *)svga->p; @@ -1926,7 +2017,7 @@ s3_io_set_alt(s3_t *s3) if (!s3->translate) return; - if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) return; io_sethandler(0x4148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1950,7 +2041,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0x9148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0x9548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); } - if (s3->chip == S3_VISION968) + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) io_sethandler(0x9948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1967,7 +2058,7 @@ s3_io_set_alt(s3_t *s3) io_sethandler(0xb948, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xbd48, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe148, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); - if (s3->chip == S3_VISION968) { + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0xd148, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe548, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -1984,13 +2075,13 @@ s3_io_set(s3_t *s3) io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - if ((s3->chip == S3_VISION968) && (svga->seqregs[0x90] & 0x80)) + if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 0x80)) return; 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); - if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) + if (s3->chip == S3_TRIO64 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { 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); @@ -2008,7 +2099,7 @@ s3_io_set(s3_t *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); } - if (s3->chip == S3_VISION968) + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) io_sethandler(0x9ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); else io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2025,7 +2116,7 @@ s3_io_set(s3_t *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); - if (s3->chip == S3_VISION968) { + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) { io_sethandler(0xd2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xe6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xeae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2248,9 +2339,6 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x53: case 0x58: case 0x59: case 0x5a: - if (svga->crtcreg == 0x59) - pclog("0x59 write val = %02x\n", val); - s3_updatemapping(s3); break; @@ -2387,8 +2475,8 @@ s3_in(uint16_t addr, void *p) case 0x6a: return s3->bank; /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ - case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); - case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); + case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0 : (svga->crtc[0x5a] & 0x80); } return svga->crtc[svga->crtcreg]; } @@ -2434,7 +2522,10 @@ static void s3_recalctimings(svga_t *svga) switch (svga->crtc[0x67] >> 4) { case 3: case 5: case 7: - svga->clock /= 2; + if (s3->chip != S3_VISION868) + svga->clock /= 2; + else + svga->clock *= 2; break; } @@ -2443,8 +2534,10 @@ static void s3_recalctimings(svga_t *svga) switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; - if (s3->width == 1280) - svga->hdisp *= 2; + if (s3->chip != S3_VISION868) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; + } break; case 15: svga->render = svga_render_15bpp_highres; @@ -2454,8 +2547,10 @@ static void s3_recalctimings(svga_t *svga) else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } - if (s3->width == 1280) - svga->hdisp *= 2; + if (s3->chip != S3_VISION868) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; + } break; case 16: svga->render = svga_render_16bpp_highres; @@ -2465,8 +2560,10 @@ static void s3_recalctimings(svga_t *svga) else if (s3->chip != S3_VISION968) svga->hdisp /= 2; } - if (s3->width == 1280) - svga->hdisp *= 2; + if (s3->chip != S3_VISION868) { + if (s3->width == 1280 || s3->width == 1600) + svga->hdisp *= 2; + } break; case 24: svga->render = svga_render_24bpp_highres; @@ -2478,8 +2575,12 @@ static void s3_recalctimings(svga_t *svga) case 32: svga->render = svga_render_32bpp_highres; if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && - (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) - svga->hdisp /= 4; + (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { + if (s3->chip == S3_VISION868) + svga->hdisp /= 2; + else + svga->hdisp /= 4; + } if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; break; @@ -2658,6 +2759,7 @@ s3_updatemapping(s3_t *s3) case S3_TRIO64V: case S3_TRIO64V2: case S3_86C928: + case S3_VISION868: s3->linear_size = 0x400000; break; default: @@ -2672,20 +2774,17 @@ s3_updatemapping(s3_t *s3) mem_mapping_disable(&s3->linear_mapping); if (!(svga->crtc[0x53] & 0x10)) { - pclog("Linear mapping enabled at 0xa0000\n"); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; } } else { if (s3->chip >= S3_TRIO64V) s3->linear_base &= 0xfc000000; - else if (s3->chip == S3_VISION968) + else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) s3->linear_base &= 0xfe000000; - pclog("Linear mapping enabled at %08x, size = %08x\n", s3->linear_base, s3->linear_size); - mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { - pclog("Linear mapping disabled\n"); mem_mapping_disable(&s3->linear_mapping); } @@ -2698,20 +2797,16 @@ s3_updatemapping(s3_t *s3) else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); } else { - pclog("Standard MMIO enabled at 0xa0000\n"); mem_mapping_enable(&s3->mmio_mapping); } } else { - pclog("Standard MMIO disabled\n"); mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ if (svga->crtc[0x53] & 0x08) { - pclog("New MMIO enabled at %08x, CRTC59 = %02x\n", s3->linear_base + 0x1000000, svga->crtc[0x59]); mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); } else { - pclog("New MMIO disabled\n", s3->linear_base); mem_mapping_disable(&s3->new_mmio_mapping); } } @@ -2742,7 +2837,7 @@ s3_enable_fifo(s3_t *s3) if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_TRIO64V) || (s3->chip == S3_TRIO64V2) || (s3->chip == S3_VISION864) || (s3->chip == S3_VISION964) || - (s3->chip == S3_VISION968)) + (s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) return 1; /* FIFO always enabled on these chips. */ return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); @@ -2909,10 +3004,11 @@ s3_accel_in(uint16_t port, void *p) wake_fifo_thread(s3); temp = 0; if ((s3->chip >= S3_86C928) && s3_enable_fifo(s3)) { - if (!FIFO_EMPTY || s3->force_busy) + if (!FIFO_EMPTY || s3->force_busy) { temp |= 0x02; /*Hardware busy*/ - else + } else { temp |= 0x04; /*FIFO empty*/ + } s3->force_busy = 0; if (s3->data_available && (s3->chip <= S3_86C805)) { temp |= 0x01; /*Read Data available*/ @@ -3205,13 +3301,17 @@ static void s3_accel_write(uint32_t addr, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); - else + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + } else s3_accel_write_fifo(s3, addr & 0xffff, val); } @@ -3219,13 +3319,17 @@ static void s3_accel_write_w(uint32_t addr, uint16_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); - else + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + } else s3_accel_write_fifo_w(s3, addr & 0xffff, val); } @@ -3233,13 +3337,17 @@ static void s3_accel_write_l(uint32_t addr, uint32_t val, void *p) { s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); - else + if (s3_enable_fifo(s3)) { + if (svga->crtc[0x53] & 0x08) + s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); + else + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + } else s3_accel_write_fifo_l(s3, addr & 0xffff, val); } @@ -3254,12 +3362,9 @@ s3_accel_read(uint32_t addr, void *p) return 0xff; } - if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { + if (svga->crtc[0x53] & 0x08) { if ((addr >= 0x08000) && (addr <= 0x0803f)) return s3_pci_read(0, addr & 0xff, s3); - else if ((addr >= 0x083b0) && (addr <= 0x083df)) - return s3_in(addr & 0xfff, s3); - switch (addr & 0x1ffff) { case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3: case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7: @@ -3278,9 +3383,6 @@ s3_accel_read(uint32_t addr, void *p) return s3->subsys_stat; case 0x8505: return s3->subsys_cntl; - /* Video engine status - currently a dummy. */ - case 0x1809c: case 0x1809d: case 0x1809e: case 0x1809f: - return 0x00; default: return s3_accel_in(addr & 0xffff, p); } @@ -3313,8 +3415,8 @@ s3_accel_read_w(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffff; - if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { - switch (addr & 0x001fffe) { + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0x1fffe) { default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -3359,8 +3461,8 @@ s3_accel_read_l(uint32_t addr, void *p) if (!s3->enable_8514) return 0xffffffff; - if (((svga->crtc[0x53] & 0x08) && s3->chip >= S3_TRIO64V) || ((svga->crtc[0x53] & 0x18) && (s3->chip == S3_VISION968))) { - switch (addr & 0x001fffc) { + if (svga->crtc[0x53] & 0x08) { + switch (addr & 0x1fffc) { case 0x8180: temp = s3->streams.pri_ctrl; break; @@ -3428,6 +3530,45 @@ s3_accel_read_l(uint32_t addr, void *p) temp = s3->streams.sec_size; break; + case 0x18080: + temp = 0; + break; + case 0x18088: + temp = s3->videoengine.cntl; + //pclog("Video Engine control temp = %08x\n", temp); + if (s3->bpp == 1) { /*The actual bpp is decided by the guest when idf is the same as odf*/ + if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) { + if (svga->bpp == 15) + temp |= 0x600000; + else + temp |= 0x700000; + } + } else if (s3->bpp > 1) { + if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) + temp |= 0x300000; + } + break; + case 0x1808c: + temp = s3->videoengine.stretch_filt_const; + break; + case 0x18090: + temp = s3->videoengine.src_dst_step; + break; + case 0x18094: + temp = s3->videoengine.crop; + break; + case 0x18098: + temp = s3->videoengine.src_base; + break; + case 0x1809c: + temp = s3->videoengine.dest_base; + if (s3->videoengine.busy) { + temp |= (1 << 31); + } else { + temp &= ~(1 << 31); + } + break; + default: temp = s3_accel_read_w(addr, p) | (s3_accel_read_w(addr + 2, p) << 16); break; @@ -3521,7 +3662,6 @@ polygon_setup(s3_t *s3) else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; - #define MIX_READ { \ switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ { \ @@ -3840,6 +3980,360 @@ polygon_setup(s3_t *s3) } +static __inline void +convert_to_rgb32(int idf, int is_yuv, uint32_t val, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *r2, uint8_t *g2, uint8_t *b2) +{ + static double dr = 0.0, dg = 0.0, db = 0.0; + static double dY1 = 0.0, dCr = 0.0, dY2 = 0.0, dCb = 0.0; + static double dU = 0.0, dV = 0.0; + + switch (idf) { + case 0: /* 8 bpp, RGB 3-3-2 */ + dr = (double) ((val >> 5) & 0x07); + dg = (double) ((val >> 2) & 0x07); + db = (double) (val & 0x03); + dr = (dr / 7.0) * 255.0; + dg = (dg / 7.0) * 255.0; + db = (db / 3.0) * 255.0; + break; + case 3: /* 32bpp, RGB 8-8-8 */ + dr = (double) ((val >> 16) & 0xff); + dg = (double) ((val >> 8) & 0xff); + db = (double) (val & 0xff); + break; + case 4: /* YCbCr */ + if (is_yuv) { + dU = ((double) (val & 0xff)) - 128.0; + dY1 = (double) ((val >> 8) & 0xff); + dY1 = (298.0 * (dY1 - 16.0)) / 256.0; + dV = ((double) ((val >> 16) & 0xff)) - 128.0; + dY2 = (double) ((val >> 24) & 0xff); + dY2 = (298.0 * (dY2 - 16.0)) / 256.0; + + dr = (309.0 * dV) / 256.0; + dg = ((100.0 * dU) + (208.0 * dV)) / 256.0; + db = (516.0 * dU) / 256.0; + } else { + dY1 = (double) (val & 0xff); + dCr = ((double) ((val >> 8) & 0xff)) - 128.0; + dY2 = (double) ((val >> 16) & 0xff); + dCb = ((double) ((val >> 24) & 0xff)) - 128.0; + + dr = (359.0 * dCr) / 256.0; + dg = ((88.0 * dCb) + (183.0 * dCr)) / 2560.0; + db = (453.0 * dCr) / 256.0; + } + + *r = (uint8_t) round(dY1 + dr); + CLAMP(*r); + *g = (uint8_t) round(dY1 - dg); + CLAMP(*g); + *b = (uint8_t) round(dY1 + db); + CLAMP(*b); + + *r2 = (uint8_t) round(dY2 + dr); + CLAMP(*r2); + *g2 = (uint8_t) round(dY2 - dg); + CLAMP(*g2); + *b2 = (uint8_t) round(dY2 + db); + CLAMP(*b2); + return; + case 5: /* 16bpp, raw */ + case 7: /* 16bpp, RGB 5-6-5 */ + dr = (double) ((val >> 11) & 0x1f); + dg = (double) ((val >> 5) & 0x03f); + db = (double) (val & 0x1f); + dr = (dr / 31.0) * 255.0; + dg = (dg / 63.0) * 255.0; + db = (db / 31.0) * 255.0; + break; + case 6: /* 15bpp, RGB 5-5-5 */ + dr = (double) ((val >> 10) & 0x1f); + dg = (double) ((val >> 5) & 0x01f); + db = (double) (val & 0x1f); + dr = (dr / 31.0) * 255.0; + dg = (dg / 31.0) * 255.0; + db = (db / 31.0) * 255.0; + break; + } + + *r = (uint8_t) round(dr); + *g = (uint8_t) round(dg); + *b = (uint8_t) round(db); +} + + +static __inline void +convert_from_rgb32(int idf, int odf, int is_yuv, uint32_t *val, uint8_t r, uint8_t g, uint8_t b, uint8_t r2, uint8_t g2, uint8_t b2) +{ + static double dr = 0.0, dg = 0.0, db = 0.0; + static double dr2 = 0.0, dg2 = 0.0, db2 = 0.0; + static double dY1 = 0.0, dCr = 0.0, dY2 = 0.0, dCb = 0.0; + static double dU = 0.0, dV = 0.0; + + dr = (double) r; + dg = (double) g; + db = (double) b; + + switch (odf) { + case 0: /* 8 bpp, RGB 3-3-2 */ + switch (idf) { + case 3: + *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); + break; + case 5: + case 7: + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 63.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 6: + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 31.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 0: + default: + dr = (dr / 255.0) * 7.0; + dg = (dg / 255.0) * 7.0; + db = (db / 255.0) * 3.0; + *val = (((uint32_t) round(dr)) << 5) + (((uint32_t) round(dg)) << 2) + ((uint32_t) round(db)); + break; + } + break; + case 3: /* 32bpp, RGB 8-8-8 */ + *val = (((uint32_t) round(dr)) << 16) + (((uint32_t) round(dg)) << 8) + ((uint32_t) round(db)); + break; + case 4: /* YCbCr */ + dr2 = (double) r2; + dg2 = (double) g2; + db2 = (double) b2; + + if (is_yuv) { + dU = ((113046.0 * dg2) - (71552.0 * dr2) - (69488.0 * db2)) / 28509.0; + dV = ((3328.0 * dr2) + (800.0 * db2) - (4128.0 * dg2)) / 663.0; + dY1 = dr - ((309 * dV) / 256.0); + dY2 = dr2 - ((309 * dV) / 256.0); + + *val = ((uint32_t) round(dU)) + (((uint32_t) round(dY1)) << 8) + (((uint32_t) round(dV)) << 16) + (((uint32_t) round(dY2)) << 24); + } else { + dCr = ((128.0 * db2) - (128.0 * dr2)) / 47.0; + dCb = ((128.0 * dr2) - (128.0 * dg2) - (271.0 * dCr)) / 44.0; + dY1 = dr - ((359.0 * dCr) / 256.0); + dY2 = dr2 - ((359.0 * dCr) / 256.0); + + *val = ((uint32_t) round(dY1)) + (((uint32_t) round(dCr)) << 8) + (((uint32_t) round(dY2)) << 16) + (((uint32_t) round(dCb)) << 24); + } + return; + case 5: /* 16bpp, raw */ + case 7: /* 16bpp, RGB 5-6-5 */ + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 63.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 11) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + case 6: /* 15bpp, RGB 5-5-5 */ + dr = (dr / 255.0) * 31.0; + dg = (dg / 255.0) * 31.0; + db = (db / 255.0) * 31.0; + *val = (((uint32_t) round(dr)) << 10) + (((uint32_t) round(dg)) << 5) + ((uint32_t) round(db)); + break; + } +} + +/*To Do: Dithering, color space conversion.*/ +static void +s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) +{ + svga_t *svga = &s3->svga; + int idf, odf, host; + int is_yuv; + uint32_t src, dest; + uint8_t r, g, b, r2, g2, b2; + uint16_t *vram_w = (uint16_t *)svga->vram; + uint32_t *vram_l = (uint32_t *)svga->vram; + uint32_t k2 = 0, dda = 0, diff = 0; + int count = -1; + + idf = s3->videoengine.idf; + odf = s3->videoengine.odf; + is_yuv = s3->videoengine.yuv; + host = s3->videoengine.host_data; + + k2 = s3->videoengine.k2 - 0x700; + dda = s3->videoengine.dda_init_accumulator - 0xf00; + diff = 0xff - k2; + + s3->videoengine.busy = 1; + + if (host) { + if (idf == 0 && odf == 0) { + if (s3->bpp == 0) + count = 4; + else if (s3->bpp == 1) + count = 2; + else + count = 1; + } else { + if (idf == 0) + count = 4; + else if (idf == 3) + count = 1; + else + count = 2; + } + } + + if (s3->videoengine.input == 1) { + if (s3->videoengine.scale_down) { + if (s3->bpp > 1) { + s3->videoengine.sx = k2 - dda + diff; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; + } else { + s3->videoengine.sx = k2 - dda + diff - 1; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; + } + s3->videoengine.sx_scale_inc = (double)((s3->videoengine.sx_backup >> 1)); + s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double)((s3->videoengine.sx >> 1)); + } else { + s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); + s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); + + if (s3->videoengine.sx_scale_dec >= 0.5d) { + s3->videoengine.sx_scale++; + } + } + + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + s3->videoengine.input = 2; + s3->videoengine.cx = 0.0d; + s3->videoengine.dx = 0.0d; + } + + //pclog("S3 video: host data = %i, shrink = %i, scale increment = %lf, idf = %i, odf = %i, dither = %i, width = %i, dest_base = %08x, sx = %i, cpu data = %08x\n", s3->videoengine.host_data, s3->videoengine.scale_down, s3->videoengine.sx_scale_inc, s3->videoengine.idf, s3->videoengine.odf, s3->videoengine.dither, s3->width, s3->videoengine.dest_base, s3->videoengine.sx, cpu_dat); + + while (count) { + if (host) { /*Source data is CPU*/ + src = cpu_dat; + } else { /*Source data is display memory*/ + READ(s3->videoengine.src + lround(s3->videoengine.cx), src); + } + + convert_to_rgb32(idf, is_yuv, src, &r, &g, &b, &r2, &g2, &b2); + + convert_from_rgb32(idf, odf, is_yuv, &dest, r, g, b, r2, g2, b2); + + WRITE(s3->videoengine.dest + lround(s3->videoengine.dx), dest); + + if (s3->videoengine.scale_down) { /*Data shrink*/ + s3->videoengine.dx += s3->videoengine.sx_scale_inc; + if (!host) + s3->videoengine.cx += s3->videoengine.sx_scale_inc; + + s3->videoengine.sx--; + + if (host) { + if (s3->bpp == 0) { + cpu_dat >>= 8; + } else { + cpu_dat >>= 16; + } + count--; + } + + if (s3->videoengine.sx < 0) { + if (s3->bpp > 1) { + s3->videoengine.sx = k2 - dda + diff; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start; + } else { + s3->videoengine.sx = k2 - dda + diff - 1; + s3->videoengine.sx_backup = s3->videoengine.len - s3->videoengine.start - 1; + } + s3->videoengine.sx_scale_inc = (double)((s3->videoengine.sx_backup >> 1)); + s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double)((s3->videoengine.sx >> 1)); + + s3->videoengine.cx = 0.0d; + s3->videoengine.dx = 0.0d; + + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + + if (s3->videoengine.input >= 1) { + s3->videoengine.busy = 0; + return; + } + } + } else { /*Data stretch*/ + s3->videoengine.dx++; + + s3->videoengine.sx_scale -= s3->videoengine.sx_scale_dec; + s3->videoengine.sx_scale_backup = (s3->videoengine.sx_scale - s3->videoengine.sx_scale_dec); + + s3->videoengine.sx = lround(s3->videoengine.sx_scale); + s3->videoengine.sx_scale_int = lround(s3->videoengine.sx_scale_backup); + + if (s3->videoengine.sx > s3->videoengine.sx_scale_int) { + if (host) { + if (s3->bpp == 0) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + count--; + } else { + s3->videoengine.cx++; + } + } + + if (s3->videoengine.sx < 0) { + s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); + s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); + + if (s3->videoengine.sx_scale_dec >= 0.5d) { + s3->videoengine.sx_scale++; + } + + s3->videoengine.cx = 0.0d; + s3->videoengine.dx = 0.0d; + + if (s3->bpp == 0) { + s3->videoengine.dest = s3->videoengine.dest_base + s3->width; + s3->videoengine.src = s3->videoengine.src_base + s3->width; + } else if (s3->bpp == 1) { + s3->videoengine.dest = (s3->videoengine.dest_base >> 1) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 1) + s3->width; + } else { + s3->videoengine.dest = (s3->videoengine.dest_base >> 2) + s3->width; + s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; + } + + if (s3->videoengine.input >= 1) { + s3->videoengine.busy = 0; + return; + } + } + } + } +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { @@ -3870,7 +4364,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } - if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968) && (s3->accel.cmd & (1 << 11))) { + if ((s3->chip >= S3_TRIO64 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (s3->accel.cmd & (1 << 11))) { cmd |= 8; } @@ -3927,7 +4421,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0x80 : 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32 || s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0x80 : 0x80000000; break; } if (s3->bpp == 0) compare &= 0xff; @@ -4250,7 +4744,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) break; polygon_setup(s3); @@ -4349,9 +4843,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && + (s3->accel.bkgd_mix & 0xf) == 7) { - while (count-- && s3->accel.sy >= 0) + while (1) { if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) @@ -4602,7 +5097,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int error; - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) break; if (!cpu_input) { @@ -4702,7 +5197,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { int end_y1, end_y2; - if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968) + if (s3->chip != S3_TRIO64 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) break; polygon_setup(s3); @@ -4787,7 +5282,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; case 14: /*ROPBlt (Vision868/968 only)*/ - if (s3->chip != S3_VISION968) + if (s3->chip != S3_VISION968 && s3->chip != S3_VISION868) break; if (!cpu_input) /*!cpu_input is trigger to start operation*/ @@ -4940,7 +5435,7 @@ s3_pci_read(int func, int addr, void *p) case 0x03: return (s3->chip == S3_TRIO64V2) ? 0x89 : 0x88; case PCI_REG_COMMAND: - if (s3->chip == S3_VISION968) + if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ else return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ @@ -4952,13 +5447,13 @@ s3_pci_read(int func, int addr, void *p) case 0x09: return 0; /*Programming interface*/ case 0x0a: - if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) return 0x00; /*Supports VGA interface*/ else return 0x01; break; case 0x0b: - if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968) + if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) return 0x03; else return 0x00; @@ -4966,8 +5461,8 @@ s3_pci_read(int func, int addr, void *p) case 0x10: return 0x00; /*Linear frame buffer address*/ case 0x11: return 0x00; - case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968) ? 0 : (svga->crtc[0x5a] & 0x80); - case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); + case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0 : (svga->crtc[0x5a] & 0x80); + case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]); case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ case 0x31: return 0x00; @@ -4997,14 +5492,14 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) break; case 0x12: - if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968) { + if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) { svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); s3_updatemapping(s3); } break; case 0x13: - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968) ? (val & 0xfe) : val); + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (val & 0xfe) : val); s3_updatemapping(s3); break; @@ -5102,6 +5597,14 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); break; + case S3_PHOENIX_VISION868: + bios_fn = ROM_PHOENIX_VISION868; + chip = S3_VISION868; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_vlb); + break; case S3_DIAMOND_STEALTH64_964: bios_fn = ROM_DIAMOND_STEALTH64_964; chip = S3_VISION964; @@ -5302,19 +5805,12 @@ static void *s3_init(const device_t *info) } } - if (chip == S3_VISION968) { - if (s3->pci) - svga->crtc[0x36] = 2 | (0 << 2) | (1 << 4); - else - svga->crtc[0x36] = 1 | (0 << 2) | (1 << 4); - } else { - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); - } + if (s3->pci) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); + else if (s3->vlb) + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); + else + svga->crtc[0x36] = 3 | (3 << 2) | (1 << 4); if (chip >= S3_86C928) svga->crtc[0x36] |= (vram_sizes[vram] << 5); @@ -5451,8 +5947,7 @@ static void *s3_init(const device_t *info) case S3_ELSAWIN2KPROX: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ - s3->id_ext = 0xb0; - s3->id_ext_pci = 0xf0; + s3->id_ext = s3->id_ext_pci = 0xf0; s3->packed_mmio = 1; if (s3->pci) { svga->crtc[0x53] = 0x18; @@ -5471,6 +5966,29 @@ static void *s3_init(const device_t *info) svga->getclock = icd2061_getclock; break; + case S3_PHOENIX_VISION868: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Vision868*/ + s3->id_ext = 0x90; + s3->id_ext_pci = 0x80; + s3->packed_mmio = 1; + if (s3->pci) { + svga->crtc[0x53] = 0x18; + svga->crtc[0x58] = 0x10; + svga->crtc[0x59] = 0x70; + svga->crtc[0x5a] = 0x00; + svga->crtc[0x6c] = 1; + } else { + svga->crtc[0x53] = 0x00; + svga->crtc[0x59] = 0x00; + svga->crtc[0x5a] = 0x0a; + } + + svga->ramdac = device_add(&sdac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + break; + case S3_PHOENIX_TRIO32: case S3_DIAMOND_STEALTH_SE: svga->decode_mask = (4 << 20) - 1; @@ -5563,6 +6081,11 @@ static int s3_phoenix_vision864_available(void) return rom_present(ROM_PHOENIX_VISION864); } +static int s3_phoenix_vision868_available(void) +{ + return rom_present(ROM_PHOENIX_VISION868); +} + static int s3_diamond_stealth64_964_available(void) { return rom_present(ROM_DIAMOND_STEALTH64_964); @@ -6126,6 +6649,34 @@ const device_t s3_phoenix_vision864_pci_device = s3_standard_config }; +const device_t s3_phoenix_vision868_vlb_device = +{ + "Phoenix S3 Vision868 VLB", + DEVICE_VLB, + S3_PHOENIX_VISION868, + s3_init, + s3_close, + NULL, + { s3_phoenix_vision868_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + +const device_t s3_phoenix_vision868_pci_device = +{ + "Phoenix S3 Vision868 PCI", + DEVICE_PCI, + S3_PHOENIX_VISION868, + s3_init, + s3_close, + NULL, + { s3_phoenix_vision868_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + const device_t s3_diamond_stealth64_vlb_device = { "S3 Trio64 (Diamond Stealth64 DRAM) VLB", diff --git a/src/video/vid_table.c b/src/video/vid_table.c index 88304b797..065988089 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -139,6 +139,7 @@ video_cards[] = { { "n9_9fx_pci", &s3_9fx_pci_device }, { "bahamas64_pci", &s3_bahamas64_pci_device }, { "px_vision864_pci", &s3_phoenix_vision864_pci_device }, + { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, { "px_trio32_pci", &s3_phoenix_trio32_pci_device }, { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, @@ -175,6 +176,7 @@ video_cards[] = { { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, + { "px_vision868_vlb", &s3_phoenix_vision868_vlb_device }, { "px_trio32_vlb", &s3_phoenix_trio32_vlb_device }, { "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, { "px_trio64vplus_vlb", &s3_phoenix_trio64vplus_vlb_device }, From c68a36c2bb7c22ea83d5773b6529d73f36b2c88e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 22 Dec 2020 14:58:28 +0100 Subject: [PATCH 25/60] Renamed the RGB525 DAC file to the correct RGB528 name and remove excess pclog lines. --- src/include/86box/vid_svga.h | 10 +- ...gb525_ramdac.c => vid_ibm_rgb528_ramdac.c} | 134 +++++++----------- src/video/vid_s3.c | 24 ++-- src/win/Makefile.mingw | 2 +- 4 files changed, 69 insertions(+), 101 deletions(-) rename src/video/{vid_ibm_rgb525_ramdac.c => vid_ibm_rgb528_ramdac.c} (86%) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 5d3d99bd3..8c0ecea0b 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -217,10 +217,10 @@ extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t extern void bt48x_recalctimings(void *p, svga_t *svga); extern void bt48x_hwcursor_draw(svga_t *svga, int displine); -extern void ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); -extern uint8_t ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); -extern void ibm_rgb525_recalctimings(void *p, svga_t *svga); -extern void ibm_rgb525_hwcursor_draw(svga_t *svga, int displine); +extern void ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern void ibm_rgb528_recalctimings(void *p, svga_t *svga); +extern void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine); extern void icd2061_write(void *p, int val); extern float icd2061_getclock(int clock, void *p); @@ -264,7 +264,7 @@ extern const device_t bt485_ramdac_device; extern const device_t att20c505_ramdac_device; extern const device_t bt485a_ramdac_device; extern const device_t gendac_ramdac_device; -extern const device_t ibm_rgb525_ramdac_device; +extern const device_t ibm_rgb528_ramdac_device; extern const device_t ics2494an_305_device; extern const device_t ics2595_device; extern const device_t icd2061_device; diff --git a/src/video/vid_ibm_rgb525_ramdac.c b/src/video/vid_ibm_rgb528_ramdac.c similarity index 86% rename from src/video/vid_ibm_rgb525_ramdac.c rename to src/video/vid_ibm_rgb528_ramdac.c index e6ba89e77..555e08231 100644 --- a/src/video/vid_ibm_rgb525_ramdac.c +++ b/src/video/vid_ibm_rgb528_ramdac.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Emulation of the IBM RGB 525 true colour RAMDAC. + * Emulation of the IBM RGB 528 true colour RAMDAC. * * * @@ -32,7 +32,7 @@ typedef union { struct { uint8_t b :2, g :3, r :2; }; -} ibm_rgb525_pixel8_t; +} ibm_rgb528_pixel8_t; typedef union { uint16_t pixel; @@ -42,14 +42,14 @@ typedef union { struct { uint16_t b :5, g :5, r :5, c :1; }; -} ibm_rgb525_pixel16_t; +} ibm_rgb528_pixel16_t; typedef union { uint32_t pixel; struct { uint8_t b, g, r, a; }; -} ibm_rgb525_pixel32_t; +} ibm_rgb528_pixel32_t; typedef struct { @@ -59,7 +59,7 @@ typedef struct uint8_t cursor32_data[256]; uint8_t cursor64_data[1024]; uint8_t palettes[3][256]; - ibm_rgb525_pixel32_t extra_pal[4]; + ibm_rgb528_pixel32_t extra_pal[4]; int hwc_y, hwc_x; uint16_t index, smlc_part; uint8_t cmd_r0; @@ -69,20 +69,20 @@ typedef struct uint8_t cmd_r4; uint8_t status, indx_cntl; uint8_t cursor_array; -} ibm_rgb525_ramdac_t; +} ibm_rgb528_ramdac_t; void -ibm_rgb525_render_4bpp(svga_t *svga) +ibm_rgb528_render_4bpp(svga_t *svga) { int x; uint32_t *p; - ibm_rgb525_pixel32_t dat_out; + ibm_rgb528_pixel32_t dat_out; uint8_t dat; uint32_t dat32 = 0x00000000; uint64_t dat64 = 0x0000000000000000ULL; uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4; uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; @@ -158,16 +158,16 @@ ibm_rgb525_render_4bpp(svga_t *svga) void -ibm_rgb525_render_8bpp(svga_t *svga) +ibm_rgb528_render_8bpp(svga_t *svga) { int x; uint32_t *p; - ibm_rgb525_pixel32_t dat_out; + ibm_rgb528_pixel32_t dat_out; uint8_t dat; uint32_t dat32 = 0x00000000; uint64_t dat64 = 0x0000000000000000ULL; uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03; @@ -232,17 +232,17 @@ ibm_rgb525_render_8bpp(svga_t *svga) void -ibm_rgb525_render_15_16bpp(svga_t *svga) +ibm_rgb528_render_15_16bpp(svga_t *svga) { int x; uint32_t *p; - ibm_rgb525_pixel16_t *dat_ex; - ibm_rgb525_pixel32_t dat_out; + ibm_rgb528_pixel16_t *dat_ex; + ibm_rgb528_pixel32_t dat_out; uint16_t dat; uint32_t dat32 = 0x00000000; uint64_t dat64 = 0x0000000000000000ULL; uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20; uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; @@ -292,7 +292,7 @@ ibm_rgb525_render_15_16bpp(svga_t *svga) } } else dat = 0x00000000; - dat_ex = (ibm_rgb525_pixel16_t *) &dat; + dat_ex = (ibm_rgb528_pixel16_t *) &dat; if (b555_565 && (b16_dcol != 0x01)) { if (swaprb) { temp = dat_ex->r_; @@ -361,15 +361,15 @@ ibm_rgb525_render_15_16bpp(svga_t *svga) void -ibm_rgb525_render_24bpp(svga_t *svga) +ibm_rgb528_render_24bpp(svga_t *svga) { int x; uint32_t *p; - ibm_rgb525_pixel32_t *dat_ex; + ibm_rgb528_pixel32_t *dat_ex; uint32_t dat; uint64_t dat64[6]; uint8_t *dat8 = (uint8_t *) dat64; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01; uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10; @@ -387,7 +387,7 @@ ibm_rgb525_render_24bpp(svga_t *svga) svga->lastline_draw = svga->displine; for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) { - dat_ex = (ibm_rgb525_pixel32_t *) &dat; + dat_ex = (ibm_rgb528_pixel32_t *) &dat; if (svga->crtc[0x17] & 0x80) { if (vram_size == 3) { if ((x & 15) == 0) { @@ -406,7 +406,7 @@ ibm_rgb525_render_24bpp(svga_t *svga) dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL); } } - dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 15) * 3)]); + dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[((x & 15) * 3)]); } else if (vram_size == 1) { if ((x & 7) == 0) { dat64[0] = *(uint64_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); @@ -418,7 +418,7 @@ ibm_rgb525_render_24bpp(svga_t *svga) dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL); } } - dat_ex = (ibm_rgb525_pixel32_t *) &(dat8[((x & 7) * 3)]); + dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[((x & 7) * 3)]); } else dat = 0x00000000; } else @@ -454,15 +454,15 @@ ibm_rgb525_render_24bpp(svga_t *svga) void -ibm_rgb525_render_32bpp(svga_t *svga) +ibm_rgb528_render_32bpp(svga_t *svga) { int x; uint32_t *p; - ibm_rgb525_pixel32_t *dat_ex; + ibm_rgb528_pixel32_t *dat_ex; uint32_t dat = 0x00000000; uint64_t dat64 = 0x0000000000000000ULL; uint64_t dat642 = 0x0000000000000000ULL; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03; uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04; uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80; @@ -503,7 +503,7 @@ ibm_rgb525_render_32bpp(svga_t *svga) dat = *(uint32_t *)(&svga->vram[svga->ma]); } else dat = 0x00000000; - dat_ex = (ibm_rgb525_pixel32_t *) &dat; + dat_ex = (ibm_rgb528_pixel32_t *) &dat; if (swaprb) { temp = dat_ex->r; dat_ex->r = dat_ex->b; @@ -539,7 +539,7 @@ ibm_rgb525_render_32bpp(svga_t *svga) static void -ibm_rgb525_set_bpp(ibm_rgb525_ramdac_t *ramdac, svga_t *svga) +ibm_rgb528_set_bpp(ibm_rgb528_ramdac_t *ramdac, svga_t *svga) { uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6; uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02; @@ -568,24 +568,20 @@ ibm_rgb525_set_bpp(ibm_rgb525_ramdac_t *ramdac, svga_t *svga) } else svga->bpp = 8; - // pclog("svga->bpp = %i\n", svga->bpp); - svga_recalctimings(svga); } void -ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) +ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) { - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; uint16_t index; uint8_t rs = (addr & 0x03); uint16_t da_mask = 0x03ff; uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08); rs |= (!!rs2 << 2); - // pclog("[%04X:%08X] [W] RS%01X = %02X\n", CS, cpu_state.pc, rs, val); - switch (rs) { case 0x00: /* Palette Write Index Register (RS value = 0000) */ case 0x03: @@ -607,24 +603,21 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga svga_out(addr, val, svga); break; case 0x04: - // pclog("Index low: %02X\n", val); ramdac->index = (ramdac->index & 0x0700) | val; if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) ramdac->cursor_array = 1; break; case 0x05: - // pclog("Index high: %02X\n", val); ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08); if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff)) ramdac->cursor_array = 1; break; case 0x06: - // pclog("Indexed data [%03X]: %02X\n", ramdac->index, val); if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array) ramdac->indexed_data[ramdac->index] = val; switch (ramdac->index) { case 0x00a: case 0x00c: - ibm_rgb525_set_bpp(ramdac, svga); + ibm_rgb528_set_bpp(ramdac, svga); break; case 0x030: switch (val & 0xc0) { @@ -644,17 +637,11 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga svga->dac_hwcursor.addr = ramdac->smlc_part; svga->dac_hwcursor.xsize = svga->dac_hwcursor.ysize = (val & 0x04) ? 64 : 32; svga->dac_hwcursor.ena = ((val & 0x03) != 0x00); - /* pclog("%ix%i cursor %sabled at DAC buffer address %02X\n", svga->dac_hwcursor.xsize, - svga->dac_hwcursor.ysize, svga->dac_hwcursor.ena ? "en" : "dis", - svga->dac_hwcursor.addr); - pclog("Pixel order %i, mode %i, update %s\n", !!(ramdac->indexed_data[0x30] & 0x20), - ramdac->indexed_data[0x30] & 0x03, (ramdac->indexed_data[0x30] & 0x08) ? "now" : "later"); */ break; case 0x031: if (!updt_cntl) break; svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0xff00) | val; - // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); break; case 0x032: /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ @@ -665,13 +652,11 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga if (!updt_cntl) break; svga->dac_hwcursor.x = (svga->dac_hwcursor.x & 0x00ff) | (val << 8); - // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); break; case 0x033: if (!updt_cntl) break; svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0xff00) | val; - // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); break; case 0x034: /* Sign-extend the sign bit (7) to the remaining bits (6-4). */ @@ -679,16 +664,13 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga if (val & 0x80) val |= 0x70; ramdac->indexed_data[ramdac->index] = val; - if (updt_cntl) { + if (updt_cntl) svga->dac_hwcursor.y = (svga->dac_hwcursor.y & 0x00ff) | (val << 8); - // pclog("Cursor Y = %i\n", svga->dac_hwcursor.x); - } else { + else { svga->dac_hwcursor.x = ramdac->indexed_data[0x031]; svga->dac_hwcursor.x |= (ramdac->indexed_data[0x032] << 8); - // pclog("Cursor X = %i\n", svga->dac_hwcursor.x); svga->dac_hwcursor.y = ramdac->indexed_data[0x033]; svga->dac_hwcursor.y |= (val << 8); - // pclog("Cursor Y = %i\n", svga->dac_hwcursor.y); } break; case 0x035: @@ -696,14 +678,12 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga svga->dac_hwcursor.xoff = (val & 0x1f); else svga->dac_hwcursor.xoff = (val & 0x3f); - // pclog("Cursor X offset = %i\n", (int) svga->dac_hwcursor.xoff); break; case 0x036: if (svga->dac_hwcursor.xsize == 64) svga->dac_hwcursor.yoff = (val & 0x1f); else svga->dac_hwcursor.yoff = (val & 0x3f); - // pclog("Cursor Y offset = %i\n", (int) svga->dac_hwcursor.yoff); break; case 0x040: case 0x043: case 0x046: ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val; @@ -725,7 +705,7 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga break; case 0x071: svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT; - ibm_rgb525_set_bpp(ramdac, svga); + ibm_rgb528_set_bpp(ramdac, svga); break; default: break; @@ -734,7 +714,6 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga if (ramdac->index == 0x00ff) ramdac->cursor_array = 0; ramdac->index = (ramdac->index + 1) & 0x07ff; - // pclog("Index now: %03X\n", ramdac->index); } break; case 0x07: @@ -747,9 +726,9 @@ ibm_rgb525_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga uint8_t -ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) +ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) { - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; uint8_t temp = 0xff; uint8_t rs = (addr & 0x03); uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10); @@ -812,16 +791,14 @@ ibm_rgb525_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) break; } - // pclog("[%04X:%08X] [R] RS%01X = %02X\n", CS, cpu_state.pc, rs, temp); - return temp; } void -ibm_rgb525_recalctimings(void *p, svga_t *svga) +ibm_rgb528_recalctimings(void *p, svga_t *svga) { - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) p; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) p; svga->interlace = ramdac->indexed_data[0x071] & 0x20; @@ -831,19 +808,19 @@ ibm_rgb525_recalctimings(void *p, svga_t *svga) if (ramdac->indexed_data[0x071] & 0x01) { switch (svga->bpp) { case 4: - svga->render = ibm_rgb525_render_4bpp; + svga->render = ibm_rgb528_render_4bpp; break; case 8: - svga->render = ibm_rgb525_render_8bpp; + svga->render = ibm_rgb528_render_8bpp; break; case 15: case 16: - svga->render = ibm_rgb525_render_15_16bpp; + svga->render = ibm_rgb528_render_15_16bpp; break; case 24: - svga->render = ibm_rgb525_render_24bpp; + svga->render = ibm_rgb528_render_24bpp; break; case 32: - svga->render = ibm_rgb525_render_32bpp; + svga->render = ibm_rgb528_render_32bpp; break; } } @@ -854,12 +831,12 @@ ibm_rgb525_recalctimings(void *p, svga_t *svga) void -ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) +ibm_rgb528_hwcursor_draw(svga_t *svga, int displine) { uint8_t dat, four_pixels = 0x00; int x, pitch, x_pos, y_pos, offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff; uint32_t *p; - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) svga->ramdac; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac; uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20; uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03; @@ -876,10 +853,9 @@ ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) p = buffer32->line[y_pos]; for (x = 0; x < svga->dac_hwcursor_latch.xsize; x ++) { - if (!(x & 3)) { + if (!(x & 3)) four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr]; - // pclog("Pixels %i to %i: %02X at %08X\n", x, x + 3, four_pixels, svga->dac_hwcursor_latch.addr); - } + if (pix_ordr) dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03; else @@ -944,10 +920,10 @@ ibm_rgb525_hwcursor_draw(svga_t *svga, int displine) void * -ibm_rgb525_ramdac_init(const device_t *info) +ibm_rgb528_ramdac_init(const device_t *info) { - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) malloc(sizeof(ibm_rgb525_ramdac_t)); - memset(ramdac, 0, sizeof(ibm_rgb525_ramdac_t)); + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) malloc(sizeof(ibm_rgb528_ramdac_t)); + memset(ramdac, 0, sizeof(ibm_rgb528_ramdac_t)); ramdac->smlc_part = 0x0100; @@ -960,19 +936,19 @@ ibm_rgb525_ramdac_init(const device_t *info) static void -ibm_rgb525_ramdac_close(void *priv) +ibm_rgb528_ramdac_close(void *priv) { - ibm_rgb525_ramdac_t *ramdac = (ibm_rgb525_ramdac_t *) priv; + ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv; if (ramdac) free(ramdac); } -const device_t ibm_rgb525_ramdac_device = +const device_t ibm_rgb528_ramdac_device = { - "IBM RGB525 RAMDAC", + "IBM RGB528 RAMDAC", 0, 0, - ibm_rgb525_ramdac_init, ibm_rgb525_ramdac_close, + ibm_rgb528_ramdac_init, ibm_rgb528_ramdac_close, NULL, { NULL }, NULL, NULL, NULL }; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 1ccf928a0..96f587ba4 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -1428,7 +1428,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) case 0x18080: s3->videoengine.nop = 1; - //pclog("Video Engine NOP\n"); break; case 0x18088: @@ -1439,7 +1438,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3->videoengine.idf = (val >> 20) & 7; s3->videoengine.dither = !!(val & (1 << 29)); s3->videoengine.dm_index = (val >> 23) & 7; - //pclog("Video Engine cntl write = %08x, dda init acc = %08x, ODF = %i, IDF = %i, Key Mask = %i, OTT = %i\n", val, s3->videoengine.dda_init_accumulator, s3->videoengine.odf, s3->videoengine.idf, !!(val & (1 << 26)), !!(val & (1 << 28))); break; case 0x1808c: @@ -1448,14 +1446,12 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3->videoengine.k1 = (val >> 16) & 0x7ff; s3->videoengine.host_data = !!(val & (1 << 30)); s3->videoengine.scale_down = !!(val & (1 << 31)); - //pclog("Video Engine stretch/filter constants write = %08x, k2 = %08x, k1 = %08x, host data = %i, down = %i, sense = %i\n", val, s3->videoengine.k2, s3->videoengine.k1, !!(val & (1 << 30)), !!(val & (1 << 31)), !!(val & (1 << 29))); break; case 0x18090: s3->videoengine.src_dst_step = val; s3->videoengine.dst_step = val & 0x1fff; s3->videoengine.src_step = (val >> 16) & 0x1fff; - //pclog("Video Engine SRC/DST Step val = %08x, SRCStep = %i, DSTStep = %i\n", val, s3->videoengine.src_step, s3->videoengine.dst_step); break; case 0x18094: @@ -1463,7 +1459,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) s3->videoengine.len = val & 0xfff; s3->videoengine.start = (val >> 16) & 0xfff; s3->videoengine.input = 1; - //pclog("Video Engine Crop val = %08x, Length = %i, Start = %i\n", val, s3->videoengine.len, s3->videoengine.start); break; case 0x18098: @@ -2187,7 +2182,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) rs3 = 0; bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) - ibm_rgb525_ramdac_out(addr, rs2, val, svga->ramdac, svga); + ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) att49x_ramdac_out(addr, val, svga->ramdac, svga); else if (s3->chip < S3_86C928) @@ -2436,7 +2431,7 @@ s3_in(uint16_t addr, void *p) rs3 = !!(svga->crtc[0x55] & 0x02); return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || s3->chip == S3_VISION968) - return ibm_rgb525_ramdac_in(addr, rs2, svga->ramdac, svga); + return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); else if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) return att49x_ramdac_in(addr, svga->ramdac, svga); else if (s3->chip <= S3_86C924) @@ -2507,11 +2502,11 @@ static void s3_recalctimings(svga_t *svga) if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { if (s3->card_type == S3_ELSAWIN2KPROX_964) - ibm_rgb525_recalctimings(svga->ramdac, svga); + ibm_rgb528_recalctimings(svga->ramdac, svga); else bt48x_recalctimings(svga->ramdac, svga); } else if (s3->chip == S3_VISION968) - ibm_rgb525_recalctimings(svga->ramdac, svga); + ibm_rgb528_recalctimings(svga->ramdac, svga); else svga->interlace = svga->crtc[0x42] & 0x20; @@ -3535,7 +3530,6 @@ s3_accel_read_l(uint32_t addr, void *p) break; case 0x18088: temp = s3->videoengine.cntl; - //pclog("Video Engine control temp = %08x\n", temp); if (s3->bpp == 1) { /*The actual bpp is decided by the guest when idf is the same as odf*/ if (s3->videoengine.idf == 0 && s3->videoengine.odf == 0) { if (svga->bpp == 15) @@ -4220,9 +4214,7 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) s3->videoengine.cx = 0.0d; s3->videoengine.dx = 0.0d; } - - //pclog("S3 video: host data = %i, shrink = %i, scale increment = %lf, idf = %i, odf = %i, dither = %i, width = %i, dest_base = %08x, sx = %i, cpu data = %08x\n", s3->videoengine.host_data, s3->videoengine.scale_down, s3->videoengine.sx_scale_inc, s3->videoengine.idf, s3->videoengine.odf, s3->videoengine.dither, s3->width, s3->videoengine.dest_base, s3->videoengine.sx, cpu_dat); - + while (count) { if (host) { /*Source data is CPU*/ src = cpu_dat; @@ -5772,7 +5764,7 @@ static void *s3_init(const device_t *info) if (chip == S3_VISION964 && info->local != S3_ELSAWIN2KPROX_964) svga->dac_hwcursor_draw = bt48x_hwcursor_draw; else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || chip == S3_VISION968) - svga->dac_hwcursor_draw = ibm_rgb525_hwcursor_draw; + svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; if (chip >= S3_VISION964) { switch (vram) { @@ -5939,7 +5931,7 @@ static void *s3_init(const device_t *info) s3->packed_mmio = 1; svga->crtc[0x5a] = 0x0a; - svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb525_ramdac_device) : device_add(&bt485_ramdac_device); + svga->ramdac = (info->local == S3_ELSAWIN2KPROX_964) ? device_add(&ibm_rgb528_ramdac_device) : device_add(&bt485_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; @@ -5961,7 +5953,7 @@ static void *s3_init(const device_t *info) svga->crtc[0x5a] = 0x0a; } - svga->ramdac = device_add(&ibm_rgb525_ramdac_device); + svga->ramdac = device_add(&ibm_rgb528_ramdac_device); svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9cf52250d..7b7bebd19 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -742,7 +742,7 @@ VIDOBJ := video.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ vid_s3.o vid_s3_virge.o \ - vid_ibm_rgb525_ramdac.o vid_sdac_ramdac.o \ + vid_ibm_rgb528_ramdac.o vid_sdac_ramdac.o \ vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_banshee_blitter.o \ vid_voodoo_blitter.o \ From c66654b1d4f78f37741719b90c688fa079b53676 Mon Sep 17 00:00:00 2001 From: Winins0 <65453129+Winins0@users.noreply.github.com> Date: Tue, 22 Dec 2020 17:19:01 +0300 Subject: [PATCH 26/60] Machine table reorganisation. --- src/machine/machine_table.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b98e0cd7c..6ada1f11c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -56,8 +56,6 @@ const machine_type_t machine_types[] = { const machine_t machines[] = { /* 8088 Machines */ - { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, - { "[8088] Eagle PC Spirit", "eagle_pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_eaglepcspirit_init, NULL }, { "[8088] IBM PC (1981)", "ibmpc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 16, 64, 16, 0, machine_pc_init, NULL }, { "[8088] IBM PC (1982)", "ibmpc82", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 256, 256, 0, machine_pc82_init, NULL }, { "[8088] IBM PCjr", "ibmpcjr", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, @@ -65,16 +63,18 @@ const machine_t machines[] = { { "[8088] IBM XT (1986)", "ibmxt86", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 64, 0, machine_xt86_init, NULL }, { "[8088] American XT Computer", "americxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_americxt_init, NULL }, { "[8088] AMI XT clone", "amixt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, + { "[8088] Columbia Data Products MPC-1600", "mpc1600", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 512, 64, 0, machine_xt_mpc1600_init, NULL }, { "[8088] Compaq Portable", "portable", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_compaq_portable_init, NULL }, { "[8088] DTK XT clone", "dtk", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, + { "[8088] Eagle PC Spirit", "eagle_pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_eaglepcspirit_init, NULL }, { "[8088] Generic XT clone", "genxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_genxt_init, NULL }, { "[8088] Juko XT clone", "jukopc", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, - { "[8088] Multitech PC-700", "multitech_pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc700_init, NULL }, - { "[8088] NCR PC4i", "ncr_pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_ncrpc4i_init, NULL }, + { "[8088] Multitech PC-700", "multitech_pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc700_init, NULL }, + { "[8088] NCR PC4i", "ncr_pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_ncrpc4i_init, NULL }, { "[8088] Olivetti M19", "olivetti_m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_olim19_init, NULL }, { "[8088] OpenXT", "open_xt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_open_xt_init, NULL }, - { "[8088] Philips P3105/NMS9100", "philips_p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, - { "[8088] Philips P3120", "philips_p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3120_init, NULL }, + { "[8088] Philips P3105/NMS9100", "philips_p3105", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3105_init, NULL }, + { "[8088] Philips P3120", "philips_p3120", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 768, 256, 0, machine_xt_p3120_init, NULL }, { "[8088] Phoenix XT clone", "pxxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, { "[8088] Schneider EuroPC", "europc", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_XTA | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, { "[8088] Tandy 1000", "tandy", MACHINE_TYPE_8088, CPU_PKG_8088_EUROPC, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, @@ -84,9 +84,9 @@ const machine_t machines[] = { { "[8088] VTech Laser Turbo XT", "ltxt", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, #endif { "[8088] Xi8088", "xi8088", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, - { "[8088] Zenith Data Systems Z-151/152/161", "zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, - { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, - { "[8088] Zenith Data Systems SupersPort (Z-184)", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC|MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device }, + { "[8088] Zenith Data Systems Z-151/152/161", "zdsz151", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z151_init, NULL }, + { "[8088] Zenith Data Systems Z-159", "zdsz159", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_z159_init, NULL }, + { "[8088] Zenith Data Systems SupersPort (Z-184)", "zdsupers", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_xt_z184_init, z184_get_device }, /* 8086 Machines */ { "[8086] Amstrad PC1512", "pc1512", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 8000000, 8000000, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, From 59bbfdd019fd8205157360072488afc81e1eca17 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 23 Dec 2020 18:00:53 +0200 Subject: [PATCH 27/60] SiS 5571 implementation A Socket 7 highly integrated chipset by SiS. Best performer for the Cyrix 6x86 CPUs of the time --- src/chipset/sis_5571.c | 628 ++++++++++++++++++++++++++++++++++++ src/include/86box/chipset.h | 3 + src/include/86box/machine.h | 5 + src/machine/m_at_socket7.c | 60 ++++ src/machine/machine_table.c | 8 +- src/win/Makefile.mingw | 11 + 6 files changed, 714 insertions(+), 1 deletion(-) create mode 100644 src/chipset/sis_5571.c diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c new file mode 100644 index 000000000..20be4af8a --- /dev/null +++ b/src/chipset/sis_5571.c @@ -0,0 +1,628 @@ +/* + * 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. + * + * Implementation of the SiS 5571 Chipset. + * + * + * + * Authors: Tiseno100, + * + * Copyright 2020 Tiseno100. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/timer.h> + +#include <86box/apm.h> +#include <86box/dma.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/port_92.h> +#include <86box/hdc_ide.h> +#include <86box/hdc_ide_sff8038i.h> +#include <86box/smram.h> +#include <86box/usb.h> + +#include <86box/chipset.h> + +#define ENABLE_SIS_5571_LOG 1 +#ifdef ENABLE_SIS_5571_LOG +int sis_5571_do_log = ENABLE_SIS_5571_LOG; +static void +sis_5571_log(const char *fmt, ...) +{ + va_list ap; + + if (sis_5571_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define sis_5571_log(fmt, ...) +#endif + +typedef struct sis_5571_t +{ + uint8_t pci_conf[256], pci_conf_sb[3][256], + sb_pci_slot; + + apm_t *apm; + port_92_t *port_92; + sff8038i_t *bm[2]; + uint32_t bus_master_base, program_status_pri, program_status_sec; + smram_t *smram; + usb_t *usb; + +} sis_5571_t; + +static void +sis_5571_shadow_recalc(sis_5571_t *dev) +{ + uint32_t i, can_read, can_write; + + for (i = 0; i < 6; i++) + { + can_read = (dev->pci_conf[0x70 + (i & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + can_write = (dev->pci_conf[0x70 + (i & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xc0000 + (0x8000 * (i & 0x07)), 0x4000, can_read | can_write); + can_read = (dev->pci_conf[0x70 + (i & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + can_write = (dev->pci_conf[0x70 + (i & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + mem_set_mem_state_both(0xc4000 + (0x8000 * (i & 0x07)), 0x4000, can_read | can_write); + } + + can_read = (dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY; + can_write = (dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY; + shadowbios = (dev->pci_conf[0x76] & 0x80); + shadowbios_write = (dev->pci_conf[0x76] & 0x20); + mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write); + + flushmmucache(); +} + +static void +sis_5571_smm_recalc(sis_5571_t *dev) +{ + switch (dev->pci_conf[0xa3] & 0xc0) + { + case 0x00: + if (!dev->pci_conf[0x74]) + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x01: + if (!dev->pci_conf[0x74]) + smram_enable(dev->smram, 0xa0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x02: + if (!dev->pci_conf[0x74]) + smram_enable(dev->smram, 0xb0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + case 0x03: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1); + break; + } + + flushmmucache(); +} + +static void +sis_5571_ide_handle(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + uint32_t base, side; + + /* IDE IRQ remap */ + if (!(dev->pci_conf_sb[0][0x63] & 0x80)) + { + sff_set_irq_line(dev->bm[0], dev->pci_conf_sb[0][0x63] & 0x0f); + sff_set_irq_line(dev->bm[1], dev->pci_conf_sb[0][0x63] & 0x0f); + } + + /* Compatibility(0)/Native(1) Mode Status Programming */ + if (dev->pci_conf_sb[1][0x08]) + dev->program_status_sec = dev->pci_conf_sb[1][0x09] & 0x04; + + if (dev->pci_conf_sb[1][0x02]) + dev->program_status_pri = dev->pci_conf_sb[1][0x09] & 0x01; + + /* Setting Base/Side */ + if (dev->program_status_pri) + { + base = ((dev->pci_conf_sb[1][0x13]) | (dev->pci_conf_sb[1][0x12] << 4) | (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10]) << 12); + side = ((dev->pci_conf_sb[1][0x17]) | (dev->pci_conf_sb[1][0x16] << 4) | (dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14]) << 12); + } + else + { + base = 0x1f0; + side = 0x3f6; + } + ide_set_base(0, base); + ide_set_side(0, side); + + if (dev->program_status_sec) + { + base = ((dev->pci_conf_sb[1][0x1b]) | (dev->pci_conf_sb[1][0x1a] << 4) | (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18]) << 12); + side = ((dev->pci_conf_sb[1][0x1f]) | (dev->pci_conf_sb[1][0x1e] << 4) | (dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c]) << 12); + } + else + { + base = 0x170; + side = 0x376; + } + ide_set_base(1, base); + ide_set_side(1, side); + + /* Enable/Disable(Default is Enabled) */ + ide_pri_disable(); + ide_sec_disable(); + + if (dev->pci_conf_sb[1][0x4a] & 0x02) + ide_pri_enable(); + + if (dev->pci_conf_sb[1][0x4a] & 0x04) + ide_sec_enable(); + + /* Bus Mastering */ + dev->bus_master_base = ((dev->pci_conf_sb[1][0x23]) | (dev->pci_conf_sb[1][0x22] << 4) | (dev->pci_conf_sb[1][0x21] << 8) | (dev->pci_conf_sb[1][0x20]) << 12); + sff_bus_master_handler(dev->bm[0], dev->pci_conf_sb[1][0x09] & 0x80, dev->bus_master_base); + sff_bus_master_handler(dev->bm[1], dev->pci_conf_sb[1][0x09] & 0x80, dev->bus_master_base + 8); +} + +static void +sis_5571_usb_handle(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + + /* USB Memory Base */ + ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[0][0x68] & 0x40); + + /* USB I/O Base*/ + uhci_update_io_mapping(dev->usb, dev->pci_conf_sb[2][0x14], dev->pci_conf_sb[2][0x17], dev->pci_conf_sb[0][0x68] & 0x40); +} + +static void +memory_pci_bridge_write(int func, int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + + switch (addr) + { + case 0x07: /* Status */ + dev->pci_conf[addr] = val & 0xbe; + break; + + case 0x50: + dev->pci_conf[addr] = val & 0xec; + break; + + case 0x51: /* Cache */ + dev->pci_conf[addr] = val; + cpu_cache_ext_enabled = (val & 0x40); + cpu_update_waitstates(); + break; + + case 0x52: + dev->pci_conf[addr] = val & 0xd0; + break; + + case 0x53: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x55: + dev->pci_conf[addr] = val & 0xe0; + break; + + case 0x56: + case 0x57: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x5a: + dev->pci_conf[addr] = val & 0x03; + break; + + case 0x70: /* Shadow RAM */ + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8); + sis_5571_shadow_recalc(dev); + sis_5571_smm_recalc(dev); + break; + + case 0x77: + dev->pci_conf[addr] = val & 0x0f; + break; + + case 0x80: + dev->pci_conf[addr] = val & 0xfe; + break; + + case 0x81: + dev->pci_conf[addr] = val & 0xcc; + break; + + case 0x83: + dev->pci_conf[addr] = val; + port_92_set_features(dev->port_92, (val & 0x40), (val & 0x80)); + break; + + case 0x87: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x93: /* APM SMI */ + dev->pci_conf[addr] = val; + apm_set_do_smi(dev->apm, ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02))); + break; + + case 0x94: + dev->pci_conf[addr] = val & 0xf8; + break; + + case 0x95: + case 0x96: + dev->pci_conf[addr] = val & 0xfb; + break; + + case 0xa3: /* SMRAM */ + dev->pci_conf[addr] = val & 0xd0; + sis_5571_smm_recalc(dev); + break; + + default: + dev->pci_conf[addr] = val; + break; + } + sis_5571_log("Memory/PCI Bridge: dev->pci_conf[%02x] = %02x\n", addr, val); +} + +static uint8_t +memory_pci_bridge_read(int func, int addr, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + sis_5571_log("Memory/PCI Bridge: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]); + return dev->pci_conf[addr]; +} + +static void +pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + switch (func) + { + case 0: /* Bridge */ + switch (addr) + { + case 0x04: + dev->pci_conf_sb[0][addr] = val & 0x0f; + break; + + case 0x40: + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; + + case 0x41: /* PCI IRQ Routing*/ + case 0x42: + case 0x43: + case 0x44: + dev->pci_conf_sb[0][addr] = val & 0x8f; + pci_set_irq_routing(PCI_INTA + (val & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x45: + case 0x46: + dev->pci_conf_sb[0][addr] = val & 0xec; + break; + + case 0x47: + dev->pci_conf_sb[0][addr] = val & 0x3e; + break; + + case 0x5f: + dev->pci_conf_sb[0][addr] = val & 0x3f; + break; + + case 0x61: /* MIRQ */ + dev->pci_conf_sb[0][addr] = val; + pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED); + break; + + case 0x62: /* DMA */ + dev->pci_conf_sb[0][addr] = val & 0x0f; + dma_set_drq((val & 0x07), 1); + break; + + case 0x63: /* IDE IRQ Remap */ + dev->pci_conf_sb[0][addr] = val & 0x8f; + sis_5571_ide_handle(dev); + break; + + case 0x64: + dev->pci_conf_sb[0][addr] = val & 0xef; + break; + + case 0x65: + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; + + case 0x68: /* USB IRQ Remap */ + dev->pci_conf_sb[0][addr] = val & 0x1b; + break; + + case 0x6a: + dev->pci_conf_sb[0][addr] = val & 0xfc; + break; + + case 0x6c: + dev->pci_conf_sb[0][addr] = val & 0x03; + break; + + case 0x70: + dev->pci_conf_sb[0][addr] = val & 0xde; + break; + + case 0x71: + dev->pci_conf_sb[0][addr] = val & 0xfe; + break; + + case 0x72: + case 0x73: + dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val; + break; + + default: + dev->pci_conf_sb[0][addr] = val; + break; + } + sis_5571_log("PCI to ISA Bridge: dev->pci_conf[%02x] = %02x\n", addr, val); + break; + + case 1: /* IDE Controller */ + switch (addr) + { + case 0x04: + dev->pci_conf_sb[1][addr] = val & 0x05; + break; + + case 0x09: + dev->pci_conf_sb[1][addr] = val & 0xcf; + break; + + default: + dev->pci_conf_sb[1][addr] = val; + break; + } + sis_5571_log("IDE Controller: dev->pci_conf[%02x] = %02x\n", addr, val); + sis_5571_ide_handle(dev); + break; + + case 2: /* USB Controller */ + switch (addr) + { + case 0x05: + dev->pci_conf_sb[2][addr] = val & 0x03; + break; + + case 0x06: + dev->pci_conf_sb[2][addr] = val & 0xc0; + break; + + default: + dev->pci_conf_sb[2][addr] = val; + break; + } + sis_5571_log("USB Controller: dev->pci_conf[%02x] = %02x\n", addr, val); + sis_5571_usb_handle(dev); + break; + } +} + +static uint8_t +pci_isa_bridge_read(int func, int addr, void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + + switch (func) + { + case 0: + sis_5571_log("PCI to ISA Bridge: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]); + return dev->pci_conf_sb[0][addr]; + case 1: + sis_5571_log("IDE Controller: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]); + return dev->pci_conf_sb[1][addr]; + case 2: + sis_5571_log("USB Controller: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]); + return dev->pci_conf_sb[2][addr]; + default: + return 0xff; + } +} + +static void +sis_5571_reset(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + + /* Memory/PCI Bridge */ + dev->pci_conf[0x00] = 0x39; + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x71; + dev->pci_conf[0x03] = 0x55; + dev->pci_conf[0x04] = 0xfd; + dev->pci_conf[0x05] = 0x00; + dev->pci_conf[0x06] = 0x00; + dev->pci_conf[0x07] = 0x00; + dev->pci_conf[0x08] = 0x00; + dev->pci_conf[0x09] = 0x00; + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + dev->pci_conf[0x0c] = 0x00; + dev->pci_conf[0x0d] = 0x00; + dev->pci_conf[0x0e] = 0x00; + dev->pci_conf[0x0f] = 0x00; + + memory_pci_bridge_write(0, 0x51, 0x00, dev); + memory_pci_bridge_write(0, 0x70, 0x00, dev); + memory_pci_bridge_write(0, 0x71, 0x00, dev); + memory_pci_bridge_write(0, 0x72, 0x00, dev); + memory_pci_bridge_write(0, 0x73, 0x00, dev); + memory_pci_bridge_write(0, 0x74, 0x00, dev); + memory_pci_bridge_write(0, 0x75, 0x00, dev); + memory_pci_bridge_write(0, 0x76, 0x00, dev); + memory_pci_bridge_write(0, 0x93, 0x00, dev); + memory_pci_bridge_write(0, 0xa3, 0x00, dev); + + /* PCI to ISA bridge */ + dev->pci_conf_sb[0][0x00] = 0x39; + dev->pci_conf_sb[0][0x01] = 0x10; + dev->pci_conf_sb[0][0x02] = 0x08; + dev->pci_conf_sb[0][0x03] = 0x00; + dev->pci_conf_sb[0][0x04] = 0xfd; + dev->pci_conf_sb[0][0x05] = 0x00; + dev->pci_conf_sb[0][0x06] = 0x00; + dev->pci_conf_sb[0][0x07] = 0x00; + dev->pci_conf_sb[0][0x08] = 0x01; + dev->pci_conf_sb[0][0x09] = 0x00; + dev->pci_conf_sb[0][0x0a] = 0x01; + dev->pci_conf_sb[0][0x0b] = 0x06; + dev->pci_conf_sb[0][0x0c] = 0x00; + dev->pci_conf_sb[0][0x0d] = 0x00; + dev->pci_conf_sb[0][0x0e] = 0x00; + dev->pci_conf_sb[0][0x0f] = 0x00; + + pci_isa_bridge_write(0, 0x41, 0x80, dev); + pci_isa_bridge_write(0, 0x42, 0x80, dev); + pci_isa_bridge_write(0, 0x43, 0x80, dev); + pci_isa_bridge_write(0, 0x44, 0x80, dev); + pci_isa_bridge_write(0, 0x61, 0x80, dev); + pci_isa_bridge_write(0, 0x62, 0x80, dev); + dev->pci_conf_sb[0][0x63] = 0x80; + + /* IDE Controller */ + dev->pci_conf_sb[1][0x00] = 0x39; + dev->pci_conf_sb[1][0x01] = 0x10; + dev->pci_conf_sb[1][0x02] = 0x13; + dev->pci_conf_sb[1][0x03] = 0x55; + dev->pci_conf_sb[1][0x04] = 0x00; + dev->pci_conf_sb[1][0x05] = 0x00; + dev->pci_conf_sb[1][0x06] = 0x00; + dev->pci_conf_sb[1][0x07] = 0x00; + dev->pci_conf_sb[1][0x08] = 0xc0; + dev->pci_conf_sb[1][0x09] = 0x00; + dev->pci_conf_sb[1][0x0a] = 0x01; + dev->pci_conf_sb[1][0x0b] = 0x01; + dev->pci_conf_sb[1][0x0c] = 0x00; + dev->pci_conf_sb[1][0x0d] = 0x00; + dev->pci_conf_sb[1][0x0e] = 0x80; + dev->pci_conf_sb[1][0x0f] = 0x00; + dev->pci_conf_sb[1][0x4a] = 0x06; + + sff_bus_master_reset(dev->bm[0], dev->bus_master_base); + sff_bus_master_reset(dev->bm[1], dev->bus_master_base + 8); + + sff_set_slot(dev->bm[0], dev->sb_pci_slot); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + + sff_set_slot(dev->bm[1], dev->sb_pci_slot); + sff_set_irq_pin(dev->bm[1], PCI_INTA); + + sis_5571_ide_handle(dev); + + /* USB Controller */ + dev->pci_conf_sb[2][0x00] = 0x39; + dev->pci_conf_sb[2][0x01] = 0x10; + dev->pci_conf_sb[2][0x02] = 0x01; + dev->pci_conf_sb[2][0x03] = 0x70; + dev->pci_conf_sb[2][0x04] = 0x00; + dev->pci_conf_sb[2][0x05] = 0x00; + dev->pci_conf_sb[2][0x06] = 0x00; + dev->pci_conf_sb[2][0x07] = 0x00; + dev->pci_conf_sb[2][0x08] = 0xb0; + dev->pci_conf_sb[2][0x09] = 0x10; + dev->pci_conf_sb[2][0x0a] = 0x03; + dev->pci_conf_sb[2][0x0b] = 0xc0; + dev->pci_conf_sb[2][0x0c] = 0x00; + dev->pci_conf_sb[2][0x0d] = 0x00; + dev->pci_conf_sb[2][0x0e] = 0x80; + dev->pci_conf_sb[2][0x0f] = 0x00; + dev->pci_conf_sb[2][0x14] = 0x01; + dev->pci_conf_sb[2][0x3d] = 0x01; + + sis_5571_usb_handle(dev); +} + +static void +sis_5571_close(void *priv) +{ + sis_5571_t *dev = (sis_5571_t *)priv; + + smram_del(dev->smram); + free(dev); +} + +static void * +sis_5571_init(const device_t *info) +{ + sis_5571_t *dev = (sis_5571_t *)malloc(sizeof(sis_5571_t)); + memset(dev, 0x00, sizeof(sis_5571_t)); + + pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev); + dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev); + pci_enable_mirq(1); + + /* APM */ + dev->apm = device_add(&apm_pci_device); + + /* DMA */ + dma_alias_set(); + + /* SFF IDE */ + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + dev->program_status_pri = 0; + dev->program_status_sec = 0; + + /* Port 92 & SMRAM */ + dev->port_92 = device_add(&port_92_pci_device); + dev->smram = smram_add(); + + /* USB */ + dev->usb = device_add(&usb_device); + + sis_5571_reset(dev); + + return dev; +} + +const device_t sis_5571_device = { + "SiS 5571", + DEVICE_PCI, + 0, + sis_5571_init, + sis_5571_close, + sis_5571_reset, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 3e27c3a8b..c6d228ddc 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -96,6 +96,9 @@ extern const device_t sis_85c471_device; extern const device_t sis_85c496_device; extern const device_t sis_85c496_ls486e_device; extern const device_t sis_85c50x_device; +#if defined(DEV_BRANCH) && defined(USE_SIS_5571) +extern const device_t sis_5571_device; +#endif /* ST */ #if defined(DEV_BRANCH) && defined(USE_STPC) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 9f572a5ef..9b75e82e1 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -425,6 +425,11 @@ extern int machine_at_an430tx_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); extern int machine_at_p5mms98_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_SIS_5571) +extern int machine_at_r534f_init(const machine_t *); +extern int machine_at_ms5146_init(const machine_t *); +#endif + extern int machine_at_ficva502_init(const machine_t *); extern int machine_at_ficpa2012_init(const machine_t *); diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index c2d2d6e5d..9e750c3c3 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -1004,6 +1004,66 @@ machine_at_p5mms98_init(const machine_t *model) return ret; } +#if defined(DEV_BRANCH) && defined(USE_SIS_5571) +int +machine_at_r534f_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/r534f/r534f008.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5571_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&sst_flash_29ee010_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 128); + + return ret; +} + +int +machine_at_ms5146_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ms5146/A546MS11.ROM", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&sis_5571_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83877f_device); + device_add(&intel_flash_bxt_device); + + return ret; +} +#endif int machine_at_ficva502_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 6ada1f11c..5fc52a9f7 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -324,7 +324,13 @@ const machine_t machines[] = { /* Apollo VP3 */ { "[VIA VP3] FIC PA-2012", "ficpa2012", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 55000000, 75000000, 2100, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 127, machine_at_ficpa2012_init, NULL }, - + + /* SiS 5571 */ +#if defined(DEV_BRANCH) && defined(USE_SIS_5571) + { "[SiS 5571] Rise R534F", "r534f", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_r534f_init, NULL }, + { "[SiS 5571] MSI MS-5146", "ms5146", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 127, machine_at_ms5146_init, NULL }, +#endif + /* Super Socket 7 machines */ /* Apollo MVP3 */ { "[VIA MVP3] AOpen AX59 Pro", "ax59pro", MACHINE_TYPE_SOCKETS7, CPU_PKG_SOCKET5_7, 0, 66666667, 124242424, 1300, 3520, 1.5, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_ax59pro_init, NULL }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 7b7bebd19..fccdcfdd2 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -84,6 +84,9 @@ ifeq ($(DEV_BUILD), y) ifndef M6117 M6117 := y endif + ifndef SIS_5571 + SIS_5571 := y + endif ifndef VGAWONDER VGAWONDER := y endif @@ -154,6 +157,9 @@ else ifndef M6117 M6117 := n endif + ifndef SIS_5571 + SIS_5571 := y + endif ifndef VGAWONDER VGAWONDER := n endif @@ -552,6 +558,11 @@ OPTS += -DUSE_M6117 DEVBROBJ += ali6117.o endif +ifeq ($(SIS_5571), y) +OPTS += -DUSE_SIS_5571 +DEVBROBJ += sis_5571.o +endif + ifeq ($(VGAWONDER), y) OPTS += -DUSE_VGAWONDER endif From 68e1b3fd9920b0cf1cd22be65fe46bce0f0bef7e Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 23 Dec 2020 18:02:22 +0200 Subject: [PATCH 28/60] Few fixes for the SiS 5571 --- src/chipset/sis_5571.c | 1 - src/win/Makefile.mingw | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 20be4af8a..e7d6050fd 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -39,7 +39,6 @@ #include <86box/chipset.h> -#define ENABLE_SIS_5571_LOG 1 #ifdef ENABLE_SIS_5571_LOG int sis_5571_do_log = ENABLE_SIS_5571_LOG; static void diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index fccdcfdd2..78977a784 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -158,7 +158,7 @@ else M6117 := n endif ifndef SIS_5571 - SIS_5571 := y + SIS_5571 := n endif ifndef VGAWONDER VGAWONDER := n From 3d516c223fa84254c643a325843b89b09b1c3f33 Mon Sep 17 00:00:00 2001 From: EngiNerd89 Date: Wed, 23 Dec 2020 20:55:09 +0100 Subject: [PATCH 29/60] Added the following new machines: - NCR PC8/810/710/3390/3392 - NCR 3302 - Olivetti M290 --- src/device/keyboard_at.c | 25 ++++++++++ src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 4 ++ src/machine/m_at_286_386sx.c | 97 ++++++++++++++++++++++++++++++++++++ src/machine/m_xt_zenith.c | 2 + src/machine/machine_table.c | 7 ++- 6 files changed, 134 insertions(+), 2 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index e63b5175d..159ca6702 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -13,10 +13,12 @@ * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, + * EngiNerd * * Copyright 2008-2020 Sarah Walker. * Copyright 2016-2020 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2020 EngiNerd. */ #include #include @@ -87,6 +89,7 @@ #define KBC_VEN_ACER 0x1c #define KBC_VEN_INTEL_AMI 0x20 #define KBC_VEN_OLIVETTI 0x24 +#define KBC_VEN_NCR 0x28 #define KBC_VEN_MASK 0x3c @@ -1197,6 +1200,17 @@ write64_generic(void *priv, uint8_t val) dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + } else if (kbc_ven == KBC_VEN_NCR) { + /* switch settings + * bit 7: keyboard disable + * bit 6: display type (0 color, 1 mono) + * bit 5: power-on default speed (0 high, 1 low) + * bit 4: sense RAM size (0 unsupported, 1 512k on system board) + * bits 0-3: unused + */ + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00)) & 0xdf); + dev->input_port = ((dev->input_port + 1) & 3) | + (dev->input_port & 0xfc); } else { if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) @@ -2277,6 +2291,7 @@ kbd_init(const device_t *info) case KBC_VEN_ACER: case KBC_VEN_GENERIC: case KBC_VEN_OLIVETTI: + case KBC_VEN_NCR: case KBC_VEN_IBM_PS1: case KBC_VEN_XI8088: dev->write64_ven = write64_generic; @@ -2350,6 +2365,16 @@ const device_t keyboard_at_olivetti_device = { { NULL }, NULL, NULL, NULL }; +const device_t keyboard_at_ncr_device = { + "PC/AT Keyboard (NCR)", + 0, + KBC_TYPE_ISA | KBC_VEN_NCR, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + const device_t keyboard_ps2_device = { "PS/2 Keyboard", 0, diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 1f69a5990..0d5b397e6 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -74,6 +74,7 @@ extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_at_olivetti_device; +extern const device_t keyboard_at_ncr_device; extern const device_t keyboard_ps2_device; extern const device_t keyboard_ps2_ps1_device; extern const device_t keyboard_ps2_ps1_pci_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 9f572a5ef..f8dd959b7 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -259,6 +259,10 @@ extern int machine_at_adi386sx_init(const machine_t *); extern int machine_at_commodore_sl386sx_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); +extern int machine_at_olim290_init(const machine_t *); +extern int machine_at_ncrpc8_init(const machine_t *); +extern int machine_at_ncr3302_init(const machine_t *); + extern int machine_at_awardsx_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_M6117) extern int machine_at_arb1375_init(const machine_t *); diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 16a21b0e0..b6a40ac4c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -12,9 +12,11 @@ * * Authors: Sarah Walker, * Miran Grca, + * EngiNerd * * Copyright 2010-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ #include #include @@ -553,3 +555,98 @@ machine_at_pja511m_init(const machine_t *model) return ret; } #endif + + + +static uint8_t +m290_read(uint16_t port, void *priv) +{ + uint8_t ret = 0x0; + switch (port) { + /* + * port 69: + * dip-switch bank on mainboard (off=1) + * bit 3 - use OCG/CGA display adapter (off) / other display adapter (on) + */ + case 0x69: + if(video_is_cga()) + ret |= 0x8|0x4; + ret |= 0x1|0x2; + } + return (ret); +} + +int +machine_at_olim290_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/olivetti_m290/m290_pep3_1.25.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_device); + device_add(&fdc_at_device); + + io_sethandler(0x069, 1, m290_read, NULL, NULL, NULL, NULL, NULL, NULL); + + return ret; +} + + +/* + * Current bugs: + * - ctrl-alt-del produces an 8042 error + */ +int +machine_at_ncrpc8_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/ncr_pc8/ncr_35117_u127_vers.4-2.bin", + L"roms/machines/ncr_pc8/ncr_35116_u113_vers.4-2.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_ncr_device); + device_add(&fdc_at_device); + + return ret; +} + +/* + * Current bugs: + * - ctrl-alt-del produces an 8042 error + */ +int +machine_at_ncr3302_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ncr_3302/f000-flex_drive_test.bin", + 0x000f0000, 65536, 0); + + if (ret) { + bios_load_aux_linear(L"roms/machines/ncr_3302/f800-setup_ncr3.5-013190.bin", + 0x000f8000, 32768, 0); + } + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + device_add(&neat_device); + device_add(&keyboard_at_ncr_device); + device_add(&fdc_at_device); + + if (gfxcard == VID_INTERNAL) + device_add(¶dise_pvga1a_device); + + return ret; +} diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 6e5ac1729..67d09a04a 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -14,9 +14,11 @@ * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, + * EngiNerd * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. + * Copyright 2020 EngiNerd. */ #include #include diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 6ada1f11c..294c3f2ea 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -121,7 +121,9 @@ const machine_t machines[] = { { "[ISA] Compaq Portable II", "portableii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_portableii_init, NULL }, { "[ISA] Compaq Portable III", "portableiii", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 640, 16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device }, { "[ISA] MR 286 clone", "mr286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 16384, 128, 127, machine_at_mr286_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) + { "[ISA] NCR PC8/810/710/3390/3392", "ncr_pc8", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_ncrpc8_init, NULL }, + { "[ISA] Olivetti M290", "olivetti_m290", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 640, 16384, 128, 127, machine_at_olim290_init, NULL }, + #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[ISA] OpenAT", "open_at", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_open_at_init, NULL }, #endif { "[ISA] Phoenix IBM AT", "ibmatpx", MACHINE_TYPE_286, CPU_PKG_286, 0, 6000000, 8000000, 0, 0, 0, 0, MACHINE_AT, 256, 15872, 128, 63, machine_at_ibmatpx_init, NULL }, @@ -131,6 +133,7 @@ const machine_t machines[] = { { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, { "[GC103] Trigem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, { "[NEAT] AMI 286 clone", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, + { "[NEAT] NCR 3302", "ncr_3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_ncr3302_init, NULL }, { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, { "[SCAT] Award 286 clone", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, @@ -365,7 +368,7 @@ const machine_t machines[] = { #if defined(DEV_BRANCH) && defined(NO_SIO) { "[i440BX] Fujitsu ErgoPro x365", "ergox365", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.5, 5.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 393216, 8192, 511, machine_at_ergox365_init, NULL }, #endif - + /* 440GX */ { "[i440GX] Freeway FW-6400GX", "fw6400gx_s1", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 100000000, 150000000, 1800, 3500, 3.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 16384,2080768,16384, 511, machine_at_fw6400gx_init, NULL }, From ad1aa692990fe5c4814367a056f5c2a7e070946a Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 23 Dec 2020 21:52:56 +0100 Subject: [PATCH 30/60] Brought the timeouts of the ESC/P and text printers in line with the PostScript printer. --- src/printer/prt_escp.c | 2 +- src/printer/prt_text.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index b30d955ef..953862c04 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1983,7 +1983,7 @@ write_ctrl(uint8_t val, void *priv) dev->ack = 1; timer_set_delay_u64(&dev->pulse_timer, ISACONST); - timer_set_delay_u64(&dev->timeout_timer, 500000 * TIMER_USEC); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } dev->ctrl = val; diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index 4024deb64..f374e83d5 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -410,7 +410,7 @@ write_ctrl(uint8_t val, void *priv) dev->ack = 1; timer_set_delay_u64(&dev->pulse_timer, ISACONST); - timer_set_delay_u64(&dev->timeout_timer, 500000 * TIMER_USEC); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); } dev->ctrl = val; From 9930957be3308d1d67c051461516113243d269da Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 24 Dec 2020 13:34:22 +0100 Subject: [PATCH 31/60] Renamed syscall() to syscall_op() in order to avoid a conflict when compiling for Linux. --- src/cpu/386_common.c | 2 +- src/cpu/cpu.h | 2 +- src/cpu/x86_ops_amd.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index a62ac4f04..5ae3304bf 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1760,7 +1760,7 @@ sysexit(uint32_t fetchdat) int -syscall(uint32_t fetchdat) +syscall_op(uint32_t fetchdat) { #ifdef ENABLE_386_COMMON_LOG x386_common_log("SYSCALL called\n"); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 6e13695ab..43413f5ce 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -578,7 +578,7 @@ extern void update_tsc(void); extern int sysenter(uint32_t fetchdat); extern int sysexit(uint32_t fetchdat); -extern int syscall(uint32_t fetchdat); +extern int syscall_op(uint32_t fetchdat); extern int sysret(uint32_t fetchdat); extern cpu_family_t *cpu_get_family(const char *internal_name); diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index 439cb2a43..0674c8187 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -20,7 +20,7 @@ opSYSCALL(uint32_t fetchdat) ILLEGAL_ON(!(amd_efer & 0x0000000000000001)); - ret = syscall(fetchdat); + ret = syscall_op(fetchdat); if (ret <= 1) { CLOCK_CYCLES(20); From d8b695b76c86a0df532021c811ac4ea89c1703e0 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Thu, 24 Dec 2020 20:11:21 +0200 Subject: [PATCH 32/60] The SiS 5571 IDE & USB handlers are now accessed when they're actually needed Fixes massive performance slowdowns. --- src/chipset/sis_5571.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index e7d6050fd..69cc13ace 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -121,7 +121,7 @@ sis_5571_smm_recalc(sis_5571_t *dev) } static void -sis_5571_ide_handle(void *priv) +sis_5571_ide_handler(void *priv) { sis_5571_t *dev = (sis_5571_t *)priv; uint32_t base, side; @@ -184,7 +184,7 @@ sis_5571_ide_handle(void *priv) } static void -sis_5571_usb_handle(void *priv) +sis_5571_usb_handler(void *priv) { sis_5571_t *dev = (sis_5571_t *)priv; @@ -354,7 +354,7 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x63: /* IDE IRQ Remap */ dev->pci_conf_sb[0][addr] = val & 0x8f; - sis_5571_ide_handle(dev); + sis_5571_ide_handler(dev); break; case 0x64: @@ -367,6 +367,7 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) case 0x68: /* USB IRQ Remap */ dev->pci_conf_sb[0][addr] = val & 0x1b; + sis_5571_usb_handler(dev); break; case 0x6a: @@ -413,7 +414,9 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) break; } sis_5571_log("IDE Controller: dev->pci_conf[%02x] = %02x\n", addr, val); - sis_5571_ide_handle(dev); + + if ((addr == 0x09) || ((addr >= 0x10) && (addr <= 0x23)) || (addr == 0x4a)) + sis_5571_ide_handler(dev); break; case 2: /* USB Controller */ @@ -432,7 +435,9 @@ pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv) break; } sis_5571_log("USB Controller: dev->pci_conf[%02x] = %02x\n", addr, val); - sis_5571_usb_handle(dev); + + if ((addr >= 0x11) && (addr <= 0x17)) + sis_5571_usb_handler(dev); break; } } @@ -546,7 +551,7 @@ sis_5571_reset(void *priv) sff_set_slot(dev->bm[1], dev->sb_pci_slot); sff_set_irq_pin(dev->bm[1], PCI_INTA); - sis_5571_ide_handle(dev); + sis_5571_ide_handler(dev); /* USB Controller */ dev->pci_conf_sb[2][0x00] = 0x39; @@ -568,7 +573,7 @@ sis_5571_reset(void *priv) dev->pci_conf_sb[2][0x14] = 0x01; dev->pci_conf_sb[2][0x3d] = 0x01; - sis_5571_usb_handle(dev); + sis_5571_usb_handler(dev); } static void From ff1d5fe966e5d80caf7d9964904040803b00a5be Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 25 Dec 2020 23:34:37 +0100 Subject: [PATCH 33/60] Window size is now set back to the remembered one when returning from Full Screen when the window is resizable and set to remember the size, fixes #1142. --- src/win/win.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/win/win.c b/src/win/win.c index 74f8d16a4..1f62f2974 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -810,12 +810,17 @@ plat_setfullscreen(int on) plat_resize(scrnsz_x, scrnsz_y); if (vid_resize) { /* scale the screen base on DPI */ - if (dpi_scale) { - temp_x = MulDiv(unscaled_size_x, dpi, 96); - temp_y = MulDiv(unscaled_size_y, dpi, 96); + if (window_remember) { + temp_x = window_w; + temp_y = window_h; } else { - temp_x = unscaled_size_x; - temp_y = unscaled_size_y; + if (dpi_scale) { + temp_x = MulDiv(unscaled_size_x, dpi, 96); + temp_y = MulDiv(unscaled_size_y, dpi, 96); + } else { + temp_x = unscaled_size_x; + temp_y = unscaled_size_y; + } } /* Main Window. */ ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); From bec9cf7faa1de7f278e55768a88fb90e0ae83111 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 26 Dec 2020 00:55:50 +0100 Subject: [PATCH 34/60] Fixed poll reading of IMD compressed sectors, fixes #1188. --- src/floppy/fdd_imd.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index a52a35c38..37c2b41da 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -268,14 +268,17 @@ sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, in { imd_t *dev = imd[drive]; int type = dev->buffer[dev->tracks[track][side].sector_data_offs[sector]]; + uint8_t fill_char; if (type == 0) memset(buffer, 0x00, len); else { if (type & 1) memcpy(buffer, &(dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]), len); - else - memset(buffer, dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1], len); + else { + fill_char = dev->buffer[dev->tracks[track][side].sector_data_offs[sector] + 1]; + memset(buffer, fill_char, len); + } } } @@ -398,6 +401,7 @@ imd_seek(int drive, int track) ssize = 128 << ((uint32_t) id[3]); sector_to_buffer(drive, track, side, data, actual_sector, ssize); + current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 22, track_gap3, flags); track_buf_pos[side] += ssize; @@ -551,9 +555,12 @@ poll_read_data(int drive, int side, uint16_t pos) imd_t *dev = imd[drive]; int type = dev->current_data[side][0]; - if (! (type & 1)) return(0xf6); /* Should never happen. */ + if ((type == 0) || (type > 8)) return(0xf6); /* Should never happen. */ - return(dev->current_data[side][pos + 1]); + if (type & 1) + return(dev->current_data[side][pos + 1]); + else + return(dev->current_data[side][1]); } @@ -565,7 +572,7 @@ poll_write_data(int drive, int side, uint16_t pos, uint8_t data) if (writeprot[drive]) return; - if (! (type & 1)) return; /* Should never happen. */ + if ((type & 1) || (type == 0) || (type > 8)) return; /* Should never happen. */ dev->current_data[side][pos + 1] = data; } @@ -720,7 +727,6 @@ imd_load(int drive, wchar_t *fn) track_spt = buffer2[3]; sector_size = buffer2[4]; - pclog("%02X %02X %02X %02X\n", buffer2[1], buffer2[2], buffer2[3], buffer2[4]); if ((track_spt == 15) && (sector_size == 2)) dev->tracks[track][side].side_flags |= 0x20; if ((track_spt == 16) && (sector_size == 2)) @@ -737,7 +743,7 @@ imd_load(int drive, wchar_t *fn) dev->tracks[track][side].max_sector_size = 5; if (!mfm) dev->tracks[track][side].max_sector_size--; - /* imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); */ + imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); dev->tracks[track][side].is_present = 1; dev->tracks[track][side].file_offs = (buffer2 - buffer); memcpy(dev->tracks[track][side].params, buffer2, 5); From fa3394c04e4d89e0152dc667693fd193ab149fce Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 26 Dec 2020 02:26:45 +0100 Subject: [PATCH 35/60] Fixed parameter list in data out phase on MODE SELECT (10) command on all ATAPI and SCSI devices, fixes ATAPI and SCSI CD Audio volume control, fixes #1191. --- src/cdrom/cdrom.c | 5 ----- src/disk/mo.c | 15 ++++++++++----- src/disk/zip.c | 15 ++++++++++----- src/scsi/scsi_cdrom.c | 12 +++++++++--- src/scsi/scsi_disk.c | 12 +++++++++--- 5 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 4b4e74d55..5db9365bc 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -733,11 +733,6 @@ track_type_is_valid(uint8_t id, int type, int flags, int audio, int mode2) } if ((type != 1) && !audio) { - if (!(flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ - cdrom_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } - if ((flags & 0x06) == 0x06) { cdrom_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); return 0; diff --git a/src/disk/mo.c b/src/disk/mo.c index 87b67c4b4..a5adbb108 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1887,8 +1887,8 @@ mo_phase_data_out(scsi_common_t *sc) { mo_t *dev = (mo_t *) sc; - uint16_t block_desc_len; - uint16_t pos; + uint16_t block_desc_len, pos; + uint16_t param_list_len; uint8_t error = 0; uint8_t page, page_len; @@ -1914,10 +1914,15 @@ mo_phase_data_out(scsi_common_t *sc) break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { hdr_len = 8; - else + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } if (dev->drv->bus_type == MO_BUS_SCSI) { if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { @@ -1935,7 +1940,7 @@ mo_phase_data_out(scsi_common_t *sc) pos = hdr_len + block_desc_len; while(1) { - if (pos >= dev->current_cdb[4]) { + if (pos >= param_list_len) { mo_log("MO %i: Buffer has only block descriptor\n", dev->id); break; } diff --git a/src/disk/zip.c b/src/disk/zip.c index 39ea4dc2a..2de8a2c0d 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -2081,8 +2081,8 @@ zip_phase_data_out(scsi_common_t *sc) { zip_t *dev = (zip_t *) sc; - uint16_t block_desc_len; - uint16_t pos; + uint16_t block_desc_len, pos; + uint16_t param_list_len; uint8_t error = 0; uint8_t page, page_len; @@ -2143,10 +2143,15 @@ zip_phase_data_out(scsi_common_t *sc) break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { hdr_len = 8; - else + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } if (dev->drv->bus_type == ZIP_BUS_SCSI) { if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { @@ -2164,7 +2169,7 @@ zip_phase_data_out(scsi_common_t *sc) pos = hdr_len + block_desc_len; while(1) { - if (pos >= dev->current_cdb[4]) { + if (pos >= param_list_len) { zip_log("ZIP %i: Buffer has only block descriptor\n", dev->id); break; } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index b1c823b46..4b148a08e 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -2490,6 +2490,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; uint16_t block_desc_len, pos; + uint16_t param_list_len; uint16_t i = 0; uint8_t error = 0; @@ -2498,10 +2499,15 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) switch(dev->current_cdb[0]) { case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { hdr_len = 8; - else + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } if (dev->drv->bus_type == CDROM_BUS_SCSI) { if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { @@ -2519,7 +2525,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) pos = hdr_len + block_desc_len; while(1) { - if (pos >= dev->current_cdb[4]) { + if (pos >= param_list_len) { scsi_cdrom_log("CD-ROM %i: Buffer has only block descriptor\n", dev->id); break; } diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 763cfd05b..e411916fa 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -1077,6 +1077,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc) uint32_t last_sector = hdd_image_get_last_sector(dev->id); uint32_t c, h, s, last_to_write = 0; uint16_t block_desc_len, pos; + uint16_t param_list_len; uint8_t hdr_len, val, old_val, ch, error = 0; uint8_t page, page_len; @@ -1133,10 +1134,15 @@ scsi_disk_phase_data_out(scsi_common_t *sc) break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) { hdr_len = 8; - else + param_list_len = dev->current_cdb[7]; + param_list_len <<= 8; + param_list_len |= dev->current_cdb[8]; + } else { hdr_len = 4; + param_list_len = dev->current_cdb[4]; + } if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { block_desc_len = dev->temp_buffer[2]; @@ -1151,7 +1157,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc) pos = hdr_len + block_desc_len; while(1) { - if (pos >= dev->current_cdb[4]) { + if (pos >= param_list_len) { scsi_disk_log("SCSI HD %i: Buffer has only block descriptor\n", dev->id); break; } From 0c3eeeb5916731955a3d17143a398ef4f38aa62a Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 26 Dec 2020 17:02:48 +0100 Subject: [PATCH 36/60] Fixed window scaling. --- src/win/win_ui.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 2b8623ce2..e72307d9b 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -662,6 +662,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) reset_screen_size(); device_force_redraw(); video_force_resize_set(1); + doresize = 1; config_save(); break; From 9f5c60c1bca7a64745728e4b7a82f30c39861c0c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 26 Dec 2020 17:21:38 +0100 Subject: [PATCH 37/60] Improved (and hopefully, properly fixed) window size and position restoring when returning back from full screen if the window is resizable and set to remember the size and position. --- src/include/86box/win.h | 2 +- src/win/win.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/include/86box/win.h b/src/include/86box/win.h index dd83af427..e73bcfd50 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -102,7 +102,7 @@ extern HANDLE ghMutex; extern LCID lang_id; extern HICON hIcon[256]; extern RECT oldclip; -extern int sbar_height; +extern int sbar_height, user_resize; // extern int status_is_open; diff --git a/src/win/win.c b/src/win/win.c index 1f62f2974..3e29062eb 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -811,8 +811,11 @@ plat_setfullscreen(int on) if (vid_resize) { /* scale the screen base on DPI */ if (window_remember) { - temp_x = window_w; - temp_y = window_h; + MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); + GetClientRect(hwndMain, &rect); + + temp_x = rect.right - rect.left + 1; + temp_y = rect.bottom - rect.top + 1 - sbar_height; } else { if (dpi_scale) { temp_x = MulDiv(unscaled_size_x, dpi, 96); @@ -821,9 +824,10 @@ plat_setfullscreen(int on) temp_x = unscaled_size_x; temp_y = unscaled_size_y; } + + /* Main Window. */ + ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); } - /* Main Window. */ - ResizeWindowByClientArea(hwndMain, temp_x, temp_y + sbar_height); /* Render window. */ MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE); From 57d0c7d5aecbcf279061da1bfc6cfa54bd138a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Sun, 27 Dec 2020 02:58:19 +0100 Subject: [PATCH 38/60] Remove non-standard `d` suffix for double literals --- src/video/vid_s3.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 96f587ba4..b9c1eba0b 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -4195,7 +4195,7 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); - if (s3->videoengine.sx_scale_dec >= 0.5d) { + if (s3->videoengine.sx_scale_dec >= 0.5) { s3->videoengine.sx_scale++; } } @@ -4211,8 +4211,8 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) s3->videoengine.src = (s3->videoengine.src_base >> 2) + s3->width; } s3->videoengine.input = 2; - s3->videoengine.cx = 0.0d; - s3->videoengine.dx = 0.0d; + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; } while (count) { @@ -4255,8 +4255,8 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) s3->videoengine.sx_scale_inc = (double)((s3->videoengine.sx_backup >> 1)); s3->videoengine.sx_scale_inc = s3->videoengine.sx_scale_inc / (double)((s3->videoengine.sx >> 1)); - s3->videoengine.cx = 0.0d; - s3->videoengine.dx = 0.0d; + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; if (s3->bpp == 0) { s3->videoengine.dest = s3->videoengine.dest_base + s3->width; @@ -4299,12 +4299,12 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) s3->videoengine.sx_scale = (double)(s3->videoengine.k1 - 2); s3->videoengine.sx_scale_dec = (s3->videoengine.sx_scale / (double)(s3->videoengine.len - s3->videoengine.start - 2)); - if (s3->videoengine.sx_scale_dec >= 0.5d) { + if (s3->videoengine.sx_scale_dec >= 0.5) { s3->videoengine.sx_scale++; } - s3->videoengine.cx = 0.0d; - s3->videoengine.dx = 0.0d; + s3->videoengine.cx = 0.0; + s3->videoengine.dx = 0.0; if (s3->bpp == 0) { s3->videoengine.dest = s3->videoengine.dest_base + s3->width; From f190c8ec7d87a994a0a156143613f020bc950374 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 27 Dec 2020 18:51:08 +0200 Subject: [PATCH 39/60] Fixes and small rework on the ALi M1489 --- src/chipset/ali1489.c | 447 ++++++++++++++++++++---------------------- 1 file changed, 218 insertions(+), 229 deletions(-) diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 180db433d..9bf301abc 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -28,19 +28,19 @@ #include <86box/timer.h> #include <86box/io.h> #include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/mem.h> -#include <86box/fdd.h> -#include <86box/fdc.h> -#include <86box/pci.h> -#include <86box/dma.h> -#include <86box/smram.h> + +#include <86box/apm.h> #include <86box/hdc_ide.h> +#include <86box/hdc.h> +#include <86box/mem.h> +#include <86box/pci.h> #include <86box/port_92.h> +#include <86box/smram.h> + #include <86box/chipset.h> -#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) -#define ENABLE_ALI1489_LOG 0 +#define DEFINE_SHADOW_PROCEDURE (((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)) +#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) #ifdef ENABLE_ALI1489_LOG int ali1489_do_log = ENABLE_ALI1489_LOG; @@ -49,10 +49,11 @@ ali1489_log(const char *fmt, ...) { va_list ap; - if (ali1489_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); + if (ali1489_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } } #else @@ -61,18 +62,23 @@ ali1489_log(const char *fmt, ...) typedef struct { - uint8_t index, ide_index, ide_chip_id, - regs[256], pci_conf[256], ide_regs[256]; - port_92_t * port_92; - smram_t * smram; + uint8_t index, ide_index, ide_chip_id, + regs[256], pci_conf[256], ide_regs[256]; + + uint8_t pci_slot; + + apm_t *apm; + port_92_t *port_92; + smram_t *smram; } ali1489_t; static void ali1489_defaults(void *priv) { - ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; /* IDE registers */ + dev->ide_regs[0x00] = 0x57; dev->ide_regs[0x01] = 0x02; dev->ide_regs[0x08] = 0xff; dev->ide_regs[0x09] = 0x41; @@ -104,266 +110,264 @@ ali1489_defaults(void *priv) dev->regs[0x3c] = 0x03; dev->regs[0x3d] = 0x01; dev->regs[0x40] = 0x03; - } static void ali1489_shadow_recalc(ali1489_t *dev) { + for (uint32_t i = 0; i < 8; i++) + { + if (dev->regs[0x13] & (1 << i)) + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DEFINE_SHADOW_PROCEDURE); + else + mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DISABLED_SHADOW); + } -uint32_t base, i; + for (uint32_t i = 0; i < 4; i++) + { + shadowbios = (dev->regs[0x14] & 0x10); + shadowbios_write = (dev->regs[0x14] & 0x20); + if (dev->regs[0x14] & (1 << i)) + mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DEFINE_SHADOW_PROCEDURE); + else + mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DISABLED_SHADOW); + } -for(i = 0; i < 8; i++){ - -base = 0xc0000 + (i << 14); -if(dev->regs[0x13] & (1 << i)) -mem_set_mem_state_both(base, 0x4000, ((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -else -mem_set_mem_state_both(base, 0x4000, disabled_shadow); - -} - - -for(i = 0; i < 4; i++){ -base = 0xe0000 + (i << 15); - -shadowbios = (dev->regs[0x14] & 0x10); -shadowbios_write = (dev->regs[0x14] & 0x20); - -if(dev->regs[0x14] & (1 << i)) -mem_set_mem_state_both(base, 0x8000, ((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); -else -mem_set_mem_state_both(base, 0x8000, disabled_shadow); -} - -flushmmucache(); + flushmmucache(); } static void ali1489_smram_recalc(ali1489_t *dev) { -/* The datasheet documents SMM behavior quite terribly. + /* The datasheet documents SMM behavior quite terribly. Everything were done according to the M1489 programming guide. */ -switch(dev->regs[0x19] & 0x30) { -case 0: -smram_disable_all(); -break; -case 1: -smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), !(dev->regs[0x19] & 0x08)); -break; -case 2: -smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), !(dev->regs[0x19] & 0x08)); -break; -case 3: -smram_enable(dev->smram, 0x30000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), !(dev->regs[0x19] & 0x08)); -break; + switch (dev->regs[0x19] & 0x30) + { + case 0: + smram_disable_all(); + break; + case 1: + smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1); + break; + case 2: + if (dev->regs[0x14] == 0) + smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1); + break; + case 3: + smram_enable(dev->smram, 0x30000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1); + break; + } } + +static void +ali1489_ide_handler(ali1489_t *dev) +{ + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + ide_pri_enable(); + if (dev->ide_regs[0x35] & 0x01) + { + ide_set_base(1, 0x170); + ide_set_side(1, 0x376); + ide_sec_enable(); + if (dev->ide_regs[0x35] & 0x04) + ide_sec_disable(); + } } static void ali1489_write(uint16_t addr, uint8_t val, void *priv) { - ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; - switch (addr) { - case 0x22: - dev->index = val; - break; - case 0x23: + switch (addr) + { + case 0x22: + dev->index = val; + break; + case 0x23: dev->regs[dev->index] = val; - if(dev->regs[0x03] == 0xc5) /* Check if the configuration registers are unlocked */ + if (dev->regs[0x03] == 0xc5) /* Check if the configuration registers are unlocked */ { - switch(dev->index){ + switch (dev->index) + { case 0x10: /* DRAM Configuration Register I */ case 0x11: /* DRAM Configuration Register II */ case 0x12: /* ROM Function Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x13: /* Shadow Region Register */ case 0x14: /* Shadow Control Register */ - if(dev->index == 0x14) - dev->regs[dev->index] = (val & 0xbf); - else - { - dev->regs[dev->index] = val; - } + if (dev->index == 0x14) + dev->regs[dev->index] = (val & 0xbf); + else + { + dev->regs[dev->index] = val; + } - ali1489_shadow_recalc(dev); - break; + ali1489_shadow_recalc(dev); + break; case 0x15: /* Cycle Check Point Control Register */ - dev->regs[dev->index] = (val & 0xf1); - break; + dev->regs[dev->index] = (val & 0xf1); + break; case 0x16: /* Cache Control Register I */ - dev->regs[dev->index] = val; - cpu_cache_int_enabled = (val & 0x01); - cpu_cache_ext_enabled = (val & 0x02); - break; + dev->regs[dev->index] = val; + cpu_cache_int_enabled = (val & 0x01); + cpu_cache_ext_enabled = (val & 0x02); + cpu_update_waitstates(); + break; case 0x17: /* Cache Control Register II */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x19: /* SMM Control Register */ - dev->regs[dev->index] = val; - ali1489_smram_recalc(dev); - break; + dev->regs[dev->index] = val; + ali1489_smram_recalc(dev); + break; case 0x1a: /* EDO DRAM Configuration Register */ case 0x1b: /* DRAM Timing Control Register */ case 0x1c: /* Memory Data Buffer Direction Control Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x1e: /* Linear Wrapped Burst Order Mode Control Register */ - dev->regs[dev->index] = (val & 0x40); - break; + dev->regs[dev->index] = (val & 0x40); + break; case 0x20: /* CPU to PCI Buffer Control Register */ case 0x21: /* DEVSELJ Check Point Setting Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x22: /* PCI to CPU W/R Buffer Configuration Register */ - dev->regs[dev->index] = (val & 0xfd); - break; + dev->regs[dev->index] = (val & 0xfd); + break; case 0x25: /* GP/MEM Address Definition Register I */ case 0x26: /* GP/MEM Address Definition Register II */ case 0x27: /* GP/MEM Address Definition Register III */ case 0x28: /* PCI Arbiter Control Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x29: /* System Clock Register */ - dev->regs[dev->index] = val; + dev->regs[dev->index] = val; - if(val & 0x10) - port_92_add(dev->port_92); - else - port_92_remove(dev->port_92); - break; + if (val & 0x10) + port_92_add(dev->port_92); + else + port_92_remove(dev->port_92); + break; case 0x2a: /* I/O Recovery Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x2b: /* Turbo Function Register */ - dev->regs[dev->index] = (val & 0xbf); - break; + dev->regs[dev->index] = (val & 0xbf); + break; case 0x30: /* Power Management Unit Control Register */ + dev->regs[dev->index] = val; + apm_set_do_smi(dev->apm, val & 0x1c); + break; + case 0x31: /* Mode Timer Monitoring Events Selection Register I */ case 0x32: /* Mode Timer Monitoring Events Selection Register II */ case 0x33: /* SMI Triggered Events Selection Register I */ case 0x34: /* SMI Triggered Events Selection Register II */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x35: /* SMI Status Register */ - dev->regs[dev->index] = val; - if(dev->regs[dev->index] & 0x30) - smi_line = 1; - break; + dev->regs[dev->index] = val; + break; case 0x36: /* IRQ Channel Group Selected Control Register I */ - dev->regs[dev->index] = (val & 0xe5); - break; + dev->regs[dev->index] = (val & 0xe5); + break; case 0x37: /* IRQ Channel Group Selected Control Register II */ - dev->regs[dev->index] = (val & 0xef); - break; + dev->regs[dev->index] = (val & 0xef); + break; case 0x38: /* DRQ Channel Selected Control Register */ case 0x39: /* Mode Timer Setting Register */ case 0x3a: /* Input_device Timer Setting Register */ case 0x3b: /* GP/MEM Timer Setting Register */ case 0x3c: /* LED Flash Control Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x3d: /* Miscellaneous Register I */ - dev->regs[dev->index] = (val & 0x07); - break; + dev->regs[dev->index] = (val & 0x07); + break; case 0x3f: /* Shadow Port 70h Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x40: /* Clock Generator Control Feature Register */ - dev->regs[dev->index] = (val & 0x3f); - break; + dev->regs[dev->index] = (val & 0x3f); + break; case 0x41: /* Power Control Output Register */ - dev->regs[dev->index] = val; - break; + dev->regs[dev->index] = val; + break; case 0x42: /* PCI INTx Routing Table Mapping Register I */ - if((val & 0x0f) != 0) - pci_set_irq(PCI_INTA, (val & 0x0f)); - else - pci_set_irq(PCI_INTA, PCI_IRQ_DISABLED); - - if(((val & 0x0f) << 4) != 0) - pci_set_irq(PCI_INTB, ((val & 0x0f) << 4)); - else - pci_set_irq(PCI_INTB, PCI_IRQ_DISABLED); - break; + pci_set_irq_routing(PCI_INTA, ((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, ((val & 0xf0) != 0) ? (val & 0xf0) : PCI_IRQ_DISABLED); + break; case 0x43: /* PCI INTx Routing Table Mapping Register II */ - if((val & 0x0f) != 0) - pci_set_irq(PCI_INTC, (val & 0x0f)); - else - pci_set_irq(PCI_INTC, PCI_IRQ_DISABLED); - - if(((val & 0x0f) << 4) != 0) - pci_set_irq(PCI_INTD, ((val & 0x0f) << 4)); - else - pci_set_irq(PCI_INTD, PCI_IRQ_DISABLED); - break; + pci_set_irq_routing(PCI_INTC, ((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, ((val & 0xf0) != 0) ? (val & 0xf0) : PCI_IRQ_DISABLED); + break; case 0x44: /* PCI INTx Sensitivity Register */ - dev->regs[dev->index] = val; - break; - + dev->regs[dev->index] = val; + break; + } + + if (dev->index != 0x03) + { + ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val); + } } - if(dev->index != 0x03) - { - ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val); - } - - } - - break; + break; } } - static uint8_t ali1489_read(uint16_t addr, void *priv) { uint8_t ret = 0xff; - ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; - switch (addr) { - case 0x23: + switch (addr) + { + case 0x23: - if(((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix) /* Avoid conflict with Cyrix CPU registers */ - ret = 0xff; + if (((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix) /* Avoid conflict with Cyrix CPU registers */ + ret = 0xff; else { - ret = dev->regs[dev->index]; + ret = dev->regs[dev->index]; } - break; + break; } - + ali1489_log("M1489: dev->regs[%02x] (%02x)\n", dev->index, ret); return ret; } @@ -371,33 +375,32 @@ static void ali1489_pci_write(int func, int addr, uint8_t val, void *priv) { -ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; -ali1489_log("M1489-PCI: dev->regs[%02x] = %02x\n", addr, val); + ali1489_log("M1489-PCI: dev->pci_conf[%02x] = %02x\n", addr, val); -switch (addr) -{ + switch (addr) + { /* Dummy PCI Config */ case 0x04: - dev->pci_conf[0x04] = (dev->pci_conf[0x04] & ~0x07) | (val & 0x07); - break; + dev->pci_conf[0x04] = (dev->pci_conf[0x04] & ~0x07) | (val & 0x07); + break; /* Dummy PCI Status */ case 0x07: - dev->pci_conf[0x07] &= ~(val & 0xfe); - break; -} - + dev->pci_conf[0x07] &= ~(val & 0xfe); + break; + } } static uint8_t ali1489_pci_read(int func, int addr, void *priv) { - ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; uint8_t ret = 0xff; - - ret = dev->pci_conf[addr]; + ret = dev->pci_conf[addr]; + ali1489_log("M1489-PCI: dev->pci_conf[%02x] (%02x)\n", addr, ret); return ret; } @@ -405,40 +408,29 @@ static void ali1489_ide_write(uint16_t addr, uint8_t val, void *priv) { -ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; - switch (addr) { + switch (addr) + { case 0xf4: /* Usually it writes 30h here */ dev->ide_chip_id = val; break; - case 0xf8: - dev->ide_index = val; - break; - - case 0xfc: - ali1489_log("M1489-IDE: dev->regs[%02x] = %02x\n", dev->ide_index, val); - dev->ide_regs[dev->ide_index] = val; + case 0xf8: + dev->ide_index = val; + break; - ide_pri_disable(); - ide_sec_disable(); - - if(dev->ide_regs[0x01] & 0x01){ /*The datasheet doesn't clearly explain the channel selection */ - ide_pri_enable(); /*So we treat it according to the chipset programming manual. */ - ide_set_base(0, 0x1f0); - ide_set_side(0, 0x3f6); - - if(!(dev->ide_regs[0x35] & 0x41)){ - ide_sec_enable(); - ide_set_base(1, 0x170); - ide_set_side(1, 0x376); + case 0xfc: + dev->ide_regs[dev->ide_index] = val; + if (dev->ide_regs[0x01] & 0x01) // Internal IDE Enabled + { + ali1489_log("M1489-IDE: dev->regs[%02x] = %02x\n", dev->ide_index, val); + ide_pri_disable(); + ide_sec_disable(); + ali1489_ide_handler(dev); } - - } - break; } - } static uint8_t @@ -446,15 +438,17 @@ ali1489_ide_read(uint16_t addr, void *priv) { uint8_t ret = 0xff; - ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; - switch (addr) { + switch (addr) + { case 0xf4: ret = dev->ide_chip_id; break; - case 0xfc: - ret = dev->ide_regs[dev->ide_index]; - break; + case 0xfc: + ret = dev->ide_regs[dev->ide_index]; + ali1489_log("M1489-IDE: dev->regs[%02x] (%02x)\n", dev->ide_index, ret); + break; } return ret; @@ -464,34 +458,29 @@ static void ali1489_reset(void *priv) { -ali1489_t *dev = (ali1489_t *) priv; + ali1489_t *dev = (ali1489_t *)priv; -ide_pri_disable(); -ide_sec_disable(); - -pci_set_irq(PCI_INTA, PCI_IRQ_DISABLED); -pci_set_irq(PCI_INTB, PCI_IRQ_DISABLED); -pci_set_irq(PCI_INTC, PCI_IRQ_DISABLED); -pci_set_irq(PCI_INTD, PCI_IRQ_DISABLED); - -ali1489_defaults(dev); + pci_set_irq(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq(PCI_INTD, PCI_IRQ_DISABLED); + ali1489_defaults(dev); } static void ali1489_close(void *priv) { - ali1489_t *dev = (ali1489_t *) priv; - + ali1489_t *dev = (ali1489_t *)priv; + smram_del(dev->smram); free(dev); } - static void * ali1489_init(const device_t *info) { - ali1489_t *dev = (ali1489_t *) malloc(sizeof(ali1489_t)); + ali1489_t *dev = (ali1489_t *)malloc(sizeof(ali1489_t)); memset(dev, 0, sizeof(ali1489_t)); /* @@ -512,11 +501,13 @@ ali1489_init(const device_t *info) io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); /* Dummy M1489 PCI device */ - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev); + dev->pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev); ide_pri_disable(); ide_sec_disable(); + dev->apm = device_add(&apm_pci_device); + device_add(&ide_pci_2ch_device); dev->port_92 = device_add(&port_92_pci_device); dev->smram = smram_add(); @@ -532,7 +523,6 @@ ali1489_init(const device_t *info) return dev; } - const device_t ali1489_device = { "ALi M1489", 0, @@ -540,8 +530,7 @@ const device_t ali1489_device = { ali1489_init, ali1489_close, ali1489_reset, - { NULL }, + {NULL}, NULL, NULL, - NULL -}; + NULL}; From 726423f00aac590575e6d1bbdb95b1fb45012ce2 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Sun, 27 Dec 2020 18:54:30 +0200 Subject: [PATCH 40/60] There's no need for the AB-PB4 to add an IDE controller The chipset does it by itself --- src/machine/m_at_386dx_486.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 74ca503d5..681e1674b 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -912,7 +912,6 @@ machine_at_abpb4_init(const machine_t *model) pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); device_add(&ali1489_device); - device_add(&ide_pci_2ch_device); device_add(&w83787f_device); device_add(&keyboard_at_device); From 8349b88c3e5292295648a1ca7b3efceb88f1c833 Mon Sep 17 00:00:00 2001 From: daviunic Date: Mon, 28 Dec 2020 00:14:04 +0100 Subject: [PATCH 41/60] Fixed get scancode set --- src/device/keyboard_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 159ca6702..05a0d6e9e 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1749,7 +1749,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) add_data_kbd_direct(dev, 0xfa); if (val == 0) { kbd_log("Get scan code set: %02X\n", keyboard_mode & 3); - add_data_kbd(keyboard_mode & 3); + add_data_kbd_direct(dev, keyboard_mode & 3); } else { if ((val <= 3) && (val != 1)) { keyboard_mode &= 0xfc; From f8dee03b4fdc3e1562f0425f9a0a20c6df5b8b55 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 28 Dec 2020 01:33:13 +0100 Subject: [PATCH 42/60] Sending CTRL+ALT+DEL and CTRL+ALT+ESC using the menu now uses the same protocol as actual key presses instead of forcibly injecting scan codes into the keyboard buffer; Fixed the machine not available string to treat the machine name string as ANSI. --- src/pc.c | 23 ++++++----------------- src/win/86Box.rc | 2 +- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/pc.c b/src/pc.c index bea9d3781..cec907027 100644 --- a/src/pc.c +++ b/src/pc.c @@ -647,26 +647,15 @@ pc_init_modules(void) } -/* Insert keystrokes into the machine's keyboard buffer. */ -static void -pc_keyboard_send(uint8_t val) -{ - if (AT) - keyboard_at_adddata_keyboard_raw(val); - else - keyboard_send(val); -} - - void pc_send_ca(uint8_t sc) { - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(sc); - pc_keyboard_send(sc | 0x80); - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(157); /* Ctrl key released */ + keyboard_input(1, 29); /* Ctrl key pressed */ + keyboard_input(1, 56); /* Alt key pressed */ + keyboard_input(1, sc); + keyboard_input(0, sc); + keyboard_input(0, 56); /* Alt key released */ + keyboard_input(0, 29); /* Ctrl key released */ } diff --git a/src/win/86Box.rc b/src/win/86Box.rc index a7891b81d..b71f49e80 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -931,7 +931,7 @@ BEGIN IDS_2060 "On" IDS_2061 "Off" IDS_2062 "All images (*.86F;*.DSK;*.FLP;*.IM?;*.*FD?)\0*.86F;*.DSK;*.FLP;*.IM?;*.*FD?\0Basic sector images (*.DSK;*.FLP;*.IM?;*.*FD?)\0*.DSK;*.FLP;*.IM?;*.IMG;*.*FD?\0Surface images (*.86F)\0*.86F\0" - IDS_2063 "Machine ""%S"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." + IDS_2063 "Machine ""%s"" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine." END STRINGTABLE DISCARDABLE From b9b753c9aa7cc494c889d2114b93680bd38506ed Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 28 Dec 2020 05:34:33 +0100 Subject: [PATCH 43/60] Fixed the SCAMP chipset emulation and the Commodore SL386SX-25 (it was using the SL386SX-16 BIOS), added the SL386-SX16 (NEAT) and the Samsung SPC-4620P, SPC-6033P, and SPC-6000A. --- src/chipset/cs8230.c | 161 ++--- src/chipset/scamp.c | 1146 +++++++++++++++++----------------- src/device/keyboard_at.c | 16 +- src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 11 +- src/include/86box/video.h | 2 + src/machine/m_at_286_386sx.c | 107 +++- src/machine/m_at_386dx_486.c | 37 +- src/machine/machine_table.c | 10 +- src/mem/mem.c | 29 +- src/video/vid_ati28800.c | 58 +- src/video/vid_cl54xx.c | 2 +- 12 files changed, 900 insertions(+), 680 deletions(-) diff --git a/src/chipset/cs8230.c b/src/chipset/cs8230.c index 90432e271..e7ae64134 100644 --- a/src/chipset/cs8230.c +++ b/src/chipset/cs8230.c @@ -32,124 +32,131 @@ typedef struct { - int idx; - uint8_t regs[256]; + int idx; + uint8_t regs[256]; } cs8230_t; + static void shadow_control(uint32_t addr, uint32_t size, int state) { - switch (state) { - case 0x00: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - case 0x01: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 0x10: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 0x11: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - } - flushmmucache_nopc(); + switch (state) { + case 0x00: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + case 0x01: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 0x10: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 0x11: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + } + + flushmmucache_nopc(); } static void rethink_shadow_mappings(cs8230_t *cs8230) { - int c; + int c; - for (c = 0; c < 4*8; c++) { /*Addresses 40000-bffff in 16k blocks*/ - if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7))) - mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /*IO channel*/ - else - mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /*System board*/ - } - for (c = 0; c < 2*8; c++) { /*Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here*/ - if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7))) - mem_set_mem_state(0xc0000 + c*0x4000, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /*IO channel*/ - else - shadow_control(0xc0000 + c*0x4000, 0x4000, (cs8230->regs[9] >> (3-(c >> 2))) & 0x11); - } + for (c = 0; c < 32; c++) { + /* Addresses 40000-bffff in 16k blocks */ + if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /* I/O channel */ + else + mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /* System board */ + } + + for (c = 0; c < 16; c++) { + /* Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here */ + if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7))) + mem_set_mem_state(0xc0000 + (c << 14), 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /* I/O channel */ + else + shadow_control(0xc0000 + (c << 14), 0x4000, (cs8230->regs[9] >> (3 - (c >> 2))) & 0x11); + } } + static uint8_t cs8230_read(uint16_t port, void *p) { - cs8230_t *cs8230 = (cs8230_t *)p; - uint8_t ret = 0xff; + cs8230_t *cs8230 = (cs8230_t *) p; + uint8_t ret = 0xff; - if (port & 1) { - switch (cs8230->idx) { - case 0x04: /*82C301 ID/version*/ - ret = cs8230->regs[cs8230->idx] & ~0xe3; - break; + if (port & 1) { + switch (cs8230->idx) { + case 0x04: /* 82C301 ID/version */ + ret = cs8230->regs[cs8230->idx] & ~0xe3; + break; - case 0x08: /*82C302 ID/Version*/ - ret = cs8230->regs[cs8230->idx] & ~0xe0; - break; - - case 0x05: case 0x06: /*82C301 registers*/ - case 0x09: case 0x0a: case 0x0b: case 0x0c: /*82C302 registers*/ - case 0x0d: case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x28: case 0x29: case 0x2a: - ret = cs8230->regs[cs8230->idx]; - break; - } + case 0x08: /* 82C302 ID/Version */ + ret = cs8230->regs[cs8230->idx] & ~0xe0; + break; + + case 0x05: case 0x06: /* 82C301 registers */ + case 0x09: case 0x0a: case 0x0b: case 0x0c: /* 82C302 registers */ + case 0x0d: case 0x0e: case 0x0f: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x28: case 0x29: case 0x2a: + ret = cs8230->regs[cs8230->idx]; + break; } + } - return ret; + return ret; } + static void cs8230_write(uint16_t port, uint8_t val, void *p) { - cs8230_t *cs8230 = (cs8230_t *)p; - - if (!(port & 1)) - cs8230->idx = val; - else { - cs8230->regs[cs8230->idx] = val; - switch (cs8230->idx) { - case 0x09: /*RAM/ROM Configuration in boot area*/ - case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /*Address maps*/ - rethink_shadow_mappings(cs8230); - break; - } + cs8230_t *cs8230 = (cs8230_t *)p; + + if (!(port & 1)) + cs8230->idx = val; + else { + cs8230->regs[cs8230->idx] = val; + switch (cs8230->idx) { + case 0x09: /* RAM/ROM Configuration in boot area */ + case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /* Address maps */ + rethink_shadow_mappings(cs8230); + break; } + } } + static void cs8230_close(void *priv) { - cs8230_t *cs8230 = (cs8230_t *)priv; - - free(cs8230); + cs8230_t *cs8230 = (cs8230_t *)priv; + + free(cs8230); } + static void *cs8230_init(const device_t *info) { - cs8230_t *cs8230 = (cs8230_t *)malloc(sizeof(cs8230_t)); - memset(cs8230, 0, sizeof(cs8230_t)); + cs8230_t *cs8230 = (cs8230_t *)malloc(sizeof(cs8230_t)); + memset(cs8230, 0, sizeof(cs8230_t)); - io_sethandler(0x0022, 0x0002, - cs8230_read, NULL, NULL, - cs8230_write, NULL, NULL, - cs8230); + io_sethandler(0x0022, 0x0002, cs8230_read, NULL, NULL, cs8230_write, NULL, NULL, cs8230); - if (mem_size > 768) { - mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000); - } + if (mem_size > 768) { + mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000); + } - return cs8230; + return cs8230; } + const device_t cs8230_device = { "C&T CS8230 (386/AT)", 0, @@ -157,4 +164,4 @@ const device_t cs8230_device = { cs8230_init, cs8230_close, NULL, { NULL }, NULL, NULL, NULL -}; \ No newline at end of file +}; diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c index 222b483f9..ea9b68d9a 100644 --- a/src/chipset/scamp.c +++ b/src/chipset/scamp.c @@ -34,28 +34,6 @@ #include <86box/port_92.h> #include <86box/chipset.h> -typedef struct { - void *parent; - int bank; -} ram_struct_t; - -typedef struct { - int cfg_index; - uint8_t cfg_regs[256]; - int cfg_enable; - - int ram_config; - - mem_mapping_t ram_mapping[2]; - - ram_struct_t ram_struct[3]; - - uint32_t ram_virt_base[2], ram_phys_base[2]; - uint32_t ram_mask[2]; - int row_virt_shift[2], row_phys_shift[2]; - int ram_interleaved[2]; - int ibank_shift[2]; -} scamp_t; #define CFG_ID 0x00 #define CFG_SLTPTR 0x02 @@ -71,697 +49,745 @@ typedef struct { #define RAMMAP_REMP386 (1 << 4) +#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) + + /*Commodore SL386SX requires proper memory slot decoding to detect memory size. Therefore we emulate the SCAMP memory address decoding, and therefore are limited to the DRAM combinations supported by the actual chip*/ enum { - BANK_NONE, - BANK_256K, - BANK_256K_INTERLEAVED, - BANK_1M, - BANK_1M_INTERLEAVED, - BANK_4M, - BANK_4M_INTERLEAVED + BANK_NONE, + BANK_256K, + BANK_256K_INTERLEAVED, + BANK_1M, + BANK_1M_INTERLEAVED, + BANK_4M, + BANK_4M_INTERLEAVED }; + +typedef struct { + void * parent; + int bank; +} ram_struct_t; + +typedef struct { + int cfg_index; + uint8_t cfg_regs[256]; + int cfg_enable, ram_config; + + mem_mapping_t ram_mapping[2]; + ram_struct_t ram_struct[2]; + + uint32_t ram_virt_base[2], ram_phys_base[2]; + uint32_t ram_mask[2]; + int row_virt_shift[2], row_phys_shift[2]; + int ram_interleaved[2], ibank_shift[2]; + + port_92_t * port_92; +} scamp_t; + static const struct { - int size_kb; - int rammap; - int bank[2]; + int size_kb; + int rammap; + int bank[2]; } ram_configs[] = { - {512, 0x0, {BANK_256K, BANK_NONE}}, - {1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}}, - {1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}}, - {2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}}, - {3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}}, - {4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}}, - {5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}}, - {6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}}, - {8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}}, - {12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}}, - {16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}}, + {512, 0x0, {BANK_256K, BANK_NONE}}, + {1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}}, + {1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}}, + {2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}}, + {3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}}, + {4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}}, + {5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}}, + {6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}}, + {8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}}, + {12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}}, + {16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}}, }; static const struct { - int bank[2]; - int remapped; + int bank[2]; + int remapped; } rammap[16] = { - {{BANK_256K, BANK_NONE}, 0}, - {{BANK_256K_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_256K_INTERLEAVED, BANK_256K}, 0}, - {{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0}, + {{BANK_256K, BANK_NONE}, 0}, + {{BANK_256K_INTERLEAVED, BANK_NONE}, 0}, + {{BANK_256K_INTERLEAVED, BANK_256K}, 0}, + {{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0}, - {{BANK_1M, BANK_NONE}, 0}, - {{BANK_1M_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_1M_INTERLEAVED, BANK_1M}, 0}, - {{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, + {{BANK_1M, BANK_NONE}, 0}, + {{BANK_1M_INTERLEAVED, BANK_NONE}, 0}, + {{BANK_1M_INTERLEAVED, BANK_1M}, 0}, + {{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, - {{BANK_4M, BANK_NONE}, 0}, - {{BANK_4M_INTERLEAVED, BANK_NONE}, 0}, - {{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/ - {{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/ + {{BANK_4M, BANK_NONE}, 0}, + {{BANK_4M_INTERLEAVED, BANK_NONE}, 0}, + {{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/ + {{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/ - {{BANK_256K_INTERLEAVED, BANK_1M}, 0}, - {{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, - {{BANK_1M_INTERLEAVED, BANK_4M}, 0}, - {{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/ + {{BANK_256K_INTERLEAVED, BANK_1M}, 0}, + {{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0}, + {{BANK_1M_INTERLEAVED, BANK_4M}, 0}, + {{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/ }; -/*The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous, - so we use separate routines for that special case*/ + +/* The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous, + so we use separate routines for that special case */ static uint8_t ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return 0xff; + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + if (!dev->ram_interleaved[bank]) { + if (addr & 0x400) + return 0xff; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); - } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + } else { + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); - } + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + } - return ram[addr + dev->ram_phys_base[bank]]; + return ram[addr + dev->ram_phys_base[bank]]; } + + static void ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return; + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + if (!dev->ram_interleaved[bank]) { + if (addr & 0x400) + return; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9); - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); - } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + } else { + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9); - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); - } + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + } - ram[addr + dev->ram_phys_base[bank]] = val; + ram[addr + dev->ram_phys_base[bank]] = val; } + /*Read/write handlers for interleaved memory banks. We must keep CPU and ram array mapping linear, otherwise we won't be able to execute code from interleaved banks*/ static uint8_t ram_mirrored_interleaved_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return 0xff; + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + if (!dev->ram_interleaved[bank]) { + if (addr & 0x400) + return 0xff; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); - } else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; - - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); - } + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + } else { + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; - return ram[addr + dev->ram_phys_base[bank]]; + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + } + + return ram[addr + dev->ram_phys_base[bank]]; } + + static void ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - if (!dev->ram_interleaved[bank]) { - if (addr & 0x400) - return; + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + if (!dev->ram_interleaved[bank]) { + if (addr & 0x400) + return; - addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1); + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); - } - else { - column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); - row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + } else { + column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1); + row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); - } + addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1)); + } - ram[addr + dev->ram_phys_base[bank]] = val; + ram[addr + dev->ram_phys_base[bank]] = val; } + static uint8_t ram_mirrored_read(uint32_t addr, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; - - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - return ram[addr + dev->ram_phys_base[bank]]; + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + + return ram[addr + dev->ram_phys_base[bank]]; } + + static void ram_mirrored_write(uint32_t addr, uint8_t val, void *priv) { - ram_struct_t *rs = (ram_struct_t *) priv; - scamp_t *dev = rs->parent; - int bank = rs->bank; - int row, column, byte; + ram_struct_t *rs = (ram_struct_t *) priv; + scamp_t *dev = rs->parent; + int bank = rs->bank, byte; + int row, column; - addr -= dev->ram_virt_base[bank]; - byte = addr & 1; - column = (addr >> 1) & dev->ram_mask[bank]; - row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; - addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); + addr -= dev->ram_virt_base[bank]; + byte = addr & 1; + column = (addr >> 1) & dev->ram_mask[bank]; + row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank]; + addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]); - ram[addr + dev->ram_phys_base[bank]] = val; + ram[addr + dev->ram_phys_base[bank]] = val; } + static void recalc_mappings(void *priv) { - scamp_t *dev = (scamp_t *) priv; - int c; - uint32_t virt_base = 0; - uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf; - int bank_nr = 0; + scamp_t *dev = (scamp_t *) priv; + int c; + uint32_t virt_base = 0, old_virt_base; + uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf; + int bank_nr = 0, phys_bank; + + mem_set_mem_state_both((1 << 20), (16256 - 1024) * 1024, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + for (c = 0; c < 2; c++) + mem_mapping_disable(&dev->ram_mapping[c]); + + /* Once the BIOS programs the correct DRAM configuration, switch to regular + linear memory mapping */ + if (cur_rammap == ram_configs[dev->ram_config].rammap) { + mem_mapping_set_handler(&ram_low_mapping, + mem_read_ram, mem_read_ramw, mem_read_raml, + mem_write_ram, mem_write_ramw, mem_write_raml); + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + if (mem_size > 1024) + mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_enable(&ram_high_mapping); + return; + } else { + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + mem_mapping_disable(&ram_low_mapping); + } + + if (rammap[cur_rammap].bank[0] == BANK_NONE) + bank_nr = 1; - for (c = 0; c < 2; c++) - mem_mapping_disable(&dev->ram_mapping[c]); + for (; bank_nr < 2; bank_nr++) { + old_virt_base = virt_base; + phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; - /*Once the BIOS programs the correct DRAM configuration, switch to regular - linear memory mapping*/ - if (cur_rammap == ram_configs[dev->ram_config].rammap) { - mem_mapping_set_handler(&ram_low_mapping, - mem_read_ram, mem_read_ramw, mem_read_raml, - mem_write_ram, mem_write_ramw, mem_write_raml); - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_enable(&ram_high_mapping); - return; - } else { - mem_mapping_set_handler(&ram_low_mapping, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - mem_mapping_disable(&ram_low_mapping); - } - - if (rammap[cur_rammap].bank[0] == BANK_NONE) - bank_nr = 1; + dev->ram_virt_base[bank_nr] = virt_base; -/* pclog("Bank remap, cur_rammap=%x\n", cur_rammap); */ - - for (; bank_nr < 2; bank_nr++) { - uint32_t old_virt_base = virt_base; - int phys_bank = ram_configs[dev->ram_config].bank[bank_nr]; - -/* pclog(" Bank %i: phys_bank=%i rammap_bank=%i virt_base=%08x phys_base=%08x\n", bank_nr, phys_bank, rammap[cur_rammap].bank[bank_nr], virt_base, dev->ram_phys_base[bank_nr]); */ - dev->ram_virt_base[bank_nr] = virt_base; + if (virt_base == 0) { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + fatal(" Bank %i is empty!\n }\n}\n", bank_nr); + break; - if (virt_base == 0) { - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - fatal("Bank 0 is empty!\n"); - break; + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - } - virt_base += 512*1024; - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - } - virt_base += 512*1024*2; - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - } - virt_base += 2048*1024; - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (3 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - } - virt_base += 2048*1024*2; - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (7 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - } - virt_base += 8192*1024; - dev->row_virt_shift[bank_nr] = 12; - break; + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); + mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); + mem_set_mem_state_both((1 << 20), (15 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; + } + } else { + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_NONE: + break; - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000); - mem_mapping_set_p(&ram_low_mapping, (void *)&dev->ram_struct[bank_nr]); - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]); - } - virt_base += 8192*1024*2; - dev->row_virt_shift[bank_nr] = 12; - break; - } - } else { - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_NONE: - break; + case BANK_256K: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 19), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 19); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_256K: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 512*1024; - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_256K_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 20); + dev->row_virt_shift[bank_nr] = 10; + break; - case BANK_256K_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 512*1024*2; - dev->row_virt_shift[bank_nr] = 10; - break; + case BANK_1M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 21), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 21); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_1M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 2048*1024; - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_1M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 22), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 22); + dev->row_virt_shift[bank_nr] = 11; + break; - case BANK_1M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 2048*1024*2; - dev->row_virt_shift[bank_nr] = 11; - break; + case BANK_4M: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 23), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 23); + dev->row_virt_shift[bank_nr] = 12; + break; - case BANK_4M: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 8192*1024; - dev->row_virt_shift[bank_nr] = 12; - break; - - case BANK_4M_INTERLEAVED: - if (phys_bank != BANK_NONE) { - mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); - mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); - } - virt_base += 8192*1024*2; - dev->row_virt_shift[bank_nr] = 12; - break; - } - } - switch (rammap[cur_rammap].bank[bank_nr]) { - case BANK_256K: case BANK_1M: case BANK_4M: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + case BANK_4M_INTERLEAVED: + if (phys_bank != BANK_NONE) { + mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000); + mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]); + mem_set_mem_state_both(virt_base, (1 << 24), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } + virt_base += (1 << 24); + dev->row_virt_shift[bank_nr] = 12; + break; + } + } + switch (rammap[cur_rammap].bank[bank_nr]) { + case BANK_256K: case BANK_1M: case BANK_4M: + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_read, NULL, NULL, ram_mirrored_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_read, NULL, NULL, ram_mirrored_write, NULL, NULL); - /*pclog(" not interleaved\n");*/ - break; + break; - case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED: - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED: + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); - /*pclog(" interleaved\n");*/ - break; + break; - case BANK_4M_INTERLEAVED: - if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + case BANK_4M_INTERLEAVED: + if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_256k_in_4mi_read, NULL, NULL, ram_mirrored_256k_in_4mi_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_256k_in_4mi_read, NULL, NULL, ram_mirrored_256k_in_4mi_write, NULL, NULL); - /*pclog(" 256k in 4mi\n");*/ - } else { - mem_mapping_set_handler(&dev->ram_mapping[bank_nr], + } else { + mem_mapping_set_handler(&dev->ram_mapping[bank_nr], ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); - if (!old_virt_base) - mem_mapping_set_handler(&ram_low_mapping, + if (!old_virt_base) + mem_mapping_set_handler(&ram_low_mapping, ram_mirrored_interleaved_read, NULL, NULL, ram_mirrored_interleaved_write, NULL, NULL); - /*pclog(" interleaved\n");*/ - } - break; - } - } + } + break; + } + } } -#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) - static void shadow_control(uint32_t addr, uint32_t size, int state) { -/* pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); */ - switch (state) { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); + switch (state) { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + + flushmmucache_nopc(); } + static void scamp_write(uint16_t addr, uint8_t val, void *priv) { - scamp_t *dev = (scamp_t *) priv; - -/* pclog("scamp_write: addr=%04x val=%02x\n", addr, val); */ - switch (addr) { - case 0xec: - if (dev->cfg_enable) - dev->cfg_index = val; - break; - - case 0xed: - if (dev->cfg_enable) { - if (dev->cfg_index >= 0x02 && dev->cfg_index <= 0x16) { - dev->cfg_regs[dev->cfg_index] = val; -/* pclog("SCAMP CFG[%02x]=%02x\n", dev->cfg_index, val); */ - switch (dev->cfg_index) { - case CFG_SLTPTR: - break; + scamp_t *dev = (scamp_t *) priv; - case CFG_RAMMAP: - recalc_mappings(dev); - mem_mapping_disable(&ram_remapped_mapping); - if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) { - /*Enabling remapping will disable all shadowing*/ - mem_remap_top(384); - shadow_control(0xa0000, 0x60000, 0); - } else { - shadow_control(0xa0000, 0x8000, dev->cfg_regs[CFG_ABAXS] & 3); - shadow_control(0xa8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 2) & 3); - shadow_control(0xb0000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 4) & 3); - shadow_control(0xb8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 6) & 3); + switch (addr) { + case 0xec: + if (dev->cfg_enable) + dev->cfg_index = val; + break; - shadow_control(0xc0000, 0x4000, dev->cfg_regs[CFG_CAXS] & 3); - shadow_control(0xc4000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 2) & 3); - shadow_control(0xc8000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 4) & 3); - shadow_control(0xcc000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 6) & 3); + case 0xed: + if (dev->cfg_enable && (dev->cfg_index >= 0x02) && (dev->cfg_index <= 0x16)) { + dev->cfg_regs[dev->cfg_index] = val; + switch (dev->cfg_index) { + case CFG_SLTPTR: + break; - shadow_control(0xd0000, 0x4000, dev->cfg_regs[CFG_DAXS] & 3); - shadow_control(0xd4000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 2) & 3); - shadow_control(0xd8000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 4) & 3); - shadow_control(0xdc000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 6) & 3); + case CFG_RAMMAP: + recalc_mappings(dev); + mem_mapping_disable(&ram_remapped_mapping); + if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) { + /* Enabling remapping will disable all shadowing */ + mem_remap_top(384); + shadow_control(0xa0000, 0x60000, 0); + } else { + shadow_control(0xa0000, 0x8000, dev->cfg_regs[CFG_ABAXS] & 3); + shadow_control(0xa8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 2) & 3); + shadow_control(0xb0000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 4) & 3); + shadow_control(0xb8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 6) & 3); - shadow_control(0xe0000, 0x8000, dev->cfg_regs[CFG_FEAXS] & 3); - shadow_control(0xe8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 2) & 3); - shadow_control(0xf0000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 4) & 3); - shadow_control(0xf8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 6) & 3); - } - break; + shadow_control(0xc0000, 0x4000, dev->cfg_regs[CFG_CAXS] & 3); + shadow_control(0xc4000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 2) & 3); + shadow_control(0xc8000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 4) & 3); + shadow_control(0xcc000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 6) & 3); - case CFG_ABAXS: - if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { - shadow_control(0xa0000, 0x8000, val & 3); - shadow_control(0xa8000, 0x8000, (val >> 2) & 3); - shadow_control(0xb0000, 0x8000, (val >> 4) & 3); - shadow_control(0xb8000, 0x8000, (val >> 6) & 3); - } - break; - - case CFG_CAXS: - if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { - shadow_control(0xc0000, 0x4000, val & 3); - shadow_control(0xc4000, 0x4000, (val >> 2) & 3); - shadow_control(0xc8000, 0x4000, (val >> 4) & 3); - shadow_control(0xcc000, 0x4000, (val >> 6) & 3); - } - break; - - case CFG_DAXS: - if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { - shadow_control(0xd0000, 0x4000, val & 3); - shadow_control(0xd4000, 0x4000, (val >> 2) & 3); - shadow_control(0xd8000, 0x4000, (val >> 4) & 3); - shadow_control(0xdc000, 0x4000, (val >> 6) & 3); - } - break; - - case CFG_FEAXS: - if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { - shadow_control(0xe0000, 0x8000, val & 3); - shadow_control(0xe8000, 0x8000, (val >> 2) & 3); - shadow_control(0xf0000, 0x8000, (val >> 4) & 3); - shadow_control(0xf8000, 0x8000, (val >> 6) & 3); - } - break; + shadow_control(0xd0000, 0x4000, dev->cfg_regs[CFG_DAXS] & 3); + shadow_control(0xd4000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 2) & 3); + shadow_control(0xd8000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 4) & 3); + shadow_control(0xdc000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 6) & 3); + + shadow_control(0xe0000, 0x8000, dev->cfg_regs[CFG_FEAXS] & 3); + shadow_control(0xe8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 2) & 3); + shadow_control(0xf0000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 4) & 3); + shadow_control(0xf8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 6) & 3); } - } - } - break; + break; - case 0xee: - if (dev->cfg_enable && mem_a20_alt) - outb(0x92, inb(0x92) & ~2); - break; - } + case CFG_ABAXS: + if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { + shadow_control(0xa0000, 0x8000, val & 3); + shadow_control(0xa8000, 0x8000, (val >> 2) & 3); + shadow_control(0xb0000, 0x8000, (val >> 4) & 3); + shadow_control(0xb8000, 0x8000, (val >> 6) & 3); + } + break; + + case CFG_CAXS: + if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { + shadow_control(0xc0000, 0x4000, val & 3); + shadow_control(0xc4000, 0x4000, (val >> 2) & 3); + shadow_control(0xc8000, 0x4000, (val >> 4) & 3); + shadow_control(0xcc000, 0x4000, (val >> 6) & 3); + } + break; + + case CFG_DAXS: + if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { + shadow_control(0xd0000, 0x4000, val & 3); + shadow_control(0xd4000, 0x4000, (val >> 2) & 3); + shadow_control(0xd8000, 0x4000, (val >> 4) & 3); + shadow_control(0xdc000, 0x4000, (val >> 6) & 3); + } + break; + + case CFG_FEAXS: + if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) { + shadow_control(0xe0000, 0x8000, val & 3); + shadow_control(0xe8000, 0x8000, (val >> 2) & 3); + shadow_control(0xf0000, 0x8000, (val >> 4) & 3); + shadow_control(0xf8000, 0x8000, (val >> 6) & 3); + } + break; + } + } + break; + + case 0xee: + if (dev->cfg_enable && mem_a20_alt) { + dev->port_92->reg &= 0xfd; + mem_a20_alt = 0; + mem_a20_recalc(); + } + break; + } } static uint8_t scamp_read(uint16_t addr, void *priv) { - uint8_t ret = 0xff; - - switch (addr) { - case 0xee: - if (!mem_a20_alt) - outb(0x92, inb(0x92) | 2); - break; - - case 0xef: - softresetx86(); - cpu_set_edx(); - break; - } + scamp_t *dev = (scamp_t *) priv; + uint8_t ret = 0xff; -/* pclog("scamp_read: addr=%04x ret=%02x\n", addr, ret); */ - return ret; + switch (addr) { + case 0xed: + if (dev->cfg_enable && (dev->cfg_index >= 0x00) && (dev->cfg_index <= 0x16)) + ret = (dev->cfg_regs[dev->cfg_index]); + break; + + case 0xee: + if (!mem_a20_alt) { + dev->port_92->reg |= 0x02; + mem_a20_alt = 1; + mem_a20_recalc(); + } + break; + + case 0xef: + softresetx86(); + cpu_set_edx(); + break; + } + + return ret; } + static void scamp_close(void *priv) { - scamp_t *dev = (scamp_t *) priv; + scamp_t *dev = (scamp_t *) priv; - free(dev); + free(dev); } static void * scamp_init(const device_t *info) { - uint32_t addr; - int c; - scamp_t *dev = (scamp_t *)malloc(sizeof(scamp_t)); - memset(dev, 0, sizeof(scamp_t)); + uint32_t addr; + int c; + scamp_t *dev = (scamp_t *)malloc(sizeof(scamp_t)); + memset(dev, 0x00, sizeof(scamp_t)); - dev->cfg_regs[CFG_ID] = ID_VL82C311; - dev->cfg_enable = 1; - - io_sethandler(0x00e8, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - io_sethandler(0x00ea, 0x0006, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - io_sethandler(0x00f4, 0x0002, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - io_sethandler(0x00f9, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - io_sethandler(0x00fb, 0x0001, - scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - - dev->ram_config = 0; + dev->cfg_regs[CFG_ID] = ID_VL82C311; + dev->cfg_enable = 1; - /*Find best fit configuration for the requested memory size*/ - for (c = 0; c < NR_ELEMS(ram_configs); c++) { - if (mem_size < ram_configs[c].size_kb) - break; - - dev->ram_config = c; - } + io_sethandler(0x00e8, 0x0001, + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + io_sethandler(0x00ea, 0x0006, + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + io_sethandler(0x00f4, 0x0002, + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + io_sethandler(0x00f9, 0x0001, + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); + io_sethandler(0x00fb, 0x0001, + scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev); - mem_mapping_set_handler(&ram_low_mapping, + dev->ram_config = 0; + + /* Find best fit configuration for the requested memory size */ + for (c = 0; c < NR_ELEMS(ram_configs); c++) { + if (mem_size < ram_configs[c].size_kb) + break; + + dev->ram_config = c; + } + + mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[0]); + mem_mapping_set_handler(&ram_low_mapping, + ram_mirrored_read, NULL, NULL, + ram_mirrored_write, NULL, NULL); + mem_mapping_disable(&ram_high_mapping); + + addr = 0; + for (c = 0; c < 2; c++) { + dev->ram_struct[c].parent = dev; + dev->ram_struct[c].bank = c; + mem_mapping_add(&dev->ram_mapping[c], 0, 0, ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL); - dev->ram_struct[2].parent = dev; - dev->ram_struct[2].bank = 0; - mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[2]); - mem_mapping_disable(&ram_high_mapping); + ram_mirrored_write, NULL, NULL, + &ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]); + mem_mapping_disable(&dev->ram_mapping[c]); - addr = 0; - for (c = 0; c < 2; c++) { - dev->ram_struct[c].parent = dev; - dev->ram_struct[c].bank = c; - mem_mapping_add(&dev->ram_mapping[c], 0, 0, - ram_mirrored_read, NULL, NULL, - ram_mirrored_write, NULL, NULL, - &ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]); - mem_mapping_disable(&dev->ram_mapping[c]); - - dev->ram_phys_base[c] = addr; -/* pclog("Bank calc : %i = %08x\n", c ,addr);*/ - - switch (ram_configs[dev->ram_config].bank[c]) { - case BANK_NONE: - dev->ram_mask[c] = 0; - dev->ram_interleaved[c] = 0; - break; - - case BANK_256K: - addr += 512*1024; - dev->ram_mask[c] = 0x1ff; - dev->row_phys_shift[c] = 10; - dev->ram_interleaved[c] = 0; - break; - - case BANK_256K_INTERLEAVED: - addr += 512*1024*2; - dev->ram_mask[c] = 0x1ff; - dev->row_phys_shift[c] = 10; - dev->ibank_shift[c] = 19; - dev->ram_interleaved[c] = 1; - break; + dev->ram_phys_base[c] = addr; - case BANK_1M: - addr += 2048*1024; - dev->ram_mask[c] = 0x3ff; - dev->row_phys_shift[c] = 11; - dev->ram_interleaved[c] = 0; - break; - - case BANK_1M_INTERLEAVED: - addr += 2048*1024*2; - dev->ram_mask[c] = 0x3ff; - dev->row_phys_shift[c] = 11; - dev->ibank_shift[c] = 21; - dev->ram_interleaved[c] = 1; - break; + switch (ram_configs[dev->ram_config].bank[c]) { + case BANK_NONE: + dev->ram_mask[c] = 0; + dev->ram_interleaved[c] = 0; + break; - case BANK_4M: - addr += 8192*1024; - dev->ram_mask[c] = 0x7ff; - dev->row_phys_shift[c] = 12; - dev->ram_interleaved[c] = 0; - break; + case BANK_256K: + addr += (1 << 19); + dev->ram_mask[c] = 0x1ff; + dev->row_phys_shift[c] = 10; + dev->ram_interleaved[c] = 0; + break; - case BANK_4M_INTERLEAVED: - addr += 8192*1024*2; - dev->ram_mask[c] = 0x7ff; - dev->row_phys_shift[c] = 12; - dev->ibank_shift[c] = 23; - dev->ram_interleaved[c] = 1; - break; - } - } - - mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - - return dev; + case BANK_256K_INTERLEAVED: + addr += (1 << 20); + dev->ram_mask[c] = 0x1ff; + dev->row_phys_shift[c] = 10; + dev->ibank_shift[c] = 19; + dev->ram_interleaved[c] = 1; + break; + + case BANK_1M: + addr += (1 << 21); + dev->ram_mask[c] = 0x3ff; + dev->row_phys_shift[c] = 11; + dev->ram_interleaved[c] = 0; + break; + + case BANK_1M_INTERLEAVED: + addr += (1 << 22); + dev->ram_mask[c] = 0x3ff; + dev->row_phys_shift[c] = 11; + dev->ibank_shift[c] = 21; + dev->ram_interleaved[c] = 1; + break; + + case BANK_4M: + addr += (1 << 23); + dev->ram_mask[c] = 0x7ff; + dev->row_phys_shift[c] = 12; + dev->ram_interleaved[c] = 0; + break; + + case BANK_4M_INTERLEAVED: + addr += (1 << 24); + dev->ram_mask[c] = 0x7ff; + dev->row_phys_shift[c] = 12; + dev->ibank_shift[c] = 23; + dev->ram_interleaved[c] = 1; + break; + } + } + + mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + + dev->port_92 = device_add(&port_92_device); + + return dev; } @@ -772,4 +798,4 @@ const device_t vlsi_scamp_device = { scamp_init, scamp_close, NULL, { NULL }, NULL, NULL, NULL -}; \ No newline at end of file +}; diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 05a0d6e9e..af2caccbd 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -89,7 +89,8 @@ #define KBC_VEN_ACER 0x1c #define KBC_VEN_INTEL_AMI 0x20 #define KBC_VEN_OLIVETTI 0x24 -#define KBC_VEN_NCR 0x28 +#define KBC_VEN_NCR 0x28 +#define KBC_VEN_SAMSUNG 0x2c #define KBC_VEN_MASK 0x3c @@ -1955,7 +1956,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xaa: /* self-test */ kbd_log("ATkbc: self-test\n"); - if (kbc_ven == KBC_VEN_TOSHIBA) + if ((kbc_ven == KBC_VEN_TOSHIBA) || (kbc_ven == KBC_VEN_SAMSUNG)) dev->status |= STAT_IFULL; if (! dev->initialized) { kbd_log("ATkbc: self-test reinitialization\n"); @@ -2299,6 +2300,7 @@ kbd_init(const device_t *info) case KBC_VEN_AMI: case KBC_VEN_INTEL_AMI: + case KBC_VEN_SAMSUNG: dev->write60_ven = write60_ami; dev->write64_ven = write64_ami; break; @@ -2345,6 +2347,16 @@ const device_t keyboard_at_ami_device = { { NULL }, NULL, NULL, NULL }; +const device_t keyboard_at_samsung_device = { + "PC/AT Keyboard (Samsung)", + 0, + KBC_TYPE_ISA | KBC_VEN_SAMSUNG, + kbd_init, + kbd_close, + kbd_reset, + { NULL }, NULL, NULL, NULL +}; + const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 0d5b397e6..6cf841df4 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -72,6 +72,7 @@ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; +extern const device_t keyboard_at_samsung_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_at_olivetti_device; extern const device_t keyboard_at_ncr_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d50b93f83..56ee11e66 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -251,12 +251,15 @@ extern int machine_at_gw286ct_init(const machine_t *); extern int machine_at_super286tr_init(const machine_t *); extern int machine_at_spc4200p_init(const machine_t *); extern int machine_at_spc4216p_init(const machine_t *); +extern int machine_at_spc4620p_init(const machine_t *); extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); extern int machine_at_shuttle386sx_init(const machine_t *); extern int machine_at_adi386sx_init(const machine_t *); -extern int machine_at_commodore_sl386sx_init(const machine_t *); +extern int machine_at_commodore_sl386sx16_init(const machine_t *); +extern int machine_at_commodore_sl386sx25_init(const machine_t *); +extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_olim290_init(const machine_t *); @@ -271,14 +274,16 @@ extern int machine_at_pja511m_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_ama932j_get_device(void); -extern const device_t *at_commodore_sl386sx_get_device(void); +extern const device_t *at_commodore_sl386sx25_get_device(void); +extern const device_t *at_spc4620p_get_device(void); +extern const device_t *at_spc6033p_get_device(void); #endif /* m_at_386dx_486.c */ - extern int machine_at_acc386_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); +extern int machine_at_spc6000a_init(const machine_t *); extern int machine_at_ustechnologies386_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index b7c356942..c619d994a 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -205,6 +205,8 @@ extern const device_t ati18800_device; /* ATi 28800 */ extern const device_t ati28800_device; extern const device_t ati28800k_device; +extern const device_t ati28800k_spc4620p_device; +extern const device_t ati28800k_spc6033p_device; extern const device_t compaq_ati28800_device; #if defined(DEV_BRANCH) && defined(USE_XL24) extern const device_t ati28800_wonderxl24_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b6a40ac4c..ef2de1226 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -37,6 +37,7 @@ #include <86box/fdc.h> #include <86box/hdc.h> #include <86box/sio.h> +#include <86box/serial.h> #include <86box/video.h> #include <86box/flash.h> #include <86box/machine.h> @@ -355,6 +356,34 @@ machine_at_spc4216p_init(const machine_t *model) } +const device_t * +at_spc4620p_get_device(void) +{ + return &ati28800k_spc4620p_device; +} + + +int +machine_at_spc4620p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/spc4620p/31005h.u8", + L"roms/machines/spc4620p/31005h.u10", + 0x000f0000, 131072, 0x8000); + + if (bios_only || !ret) + return ret; + + machine_at_scat_init(model, 1); + + if (gfxcard == VID_INTERNAL) + device_add(&ati28800k_spc4620p_device); + + return ret; +} + + int machine_at_kmxc02_init(const machine_t *model) { @@ -458,20 +487,13 @@ machine_at_wd76c10_init(const machine_t *model) } -const device_t * -at_commodore_sl386sx_get_device(void) -{ - return &gd5402_onboard_device; -} - - int -machine_at_commodore_sl386sx_init(const machine_t *model) +machine_at_commodore_sl386sx16_init(const machine_t *model) { int ret; - ret = bios_load_interleaved(L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-lo-v1.04-390914-04.bin", - L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-hi-v1.04-390915-04.bin", + ret = bios_load_interleaved(L"roms/machines/cbm_sl386sx16/cbm-sl386sx-bios-lo-v1.04-390914-04.bin", + L"roms/machines/cbm_sl386sx16/cbm-sl386sx-bios-hi-v1.04-390915-04.bin", 0x000f0000, 65536, 0); if (bios_only || !ret) @@ -481,7 +503,45 @@ machine_at_commodore_sl386sx_init(const machine_t *model) device_add(&keyboard_at_device); device_add(&fdc_at_device); + device_add(&neat_device); + /* Two serial ports - on the real hardware SL386SX-16, they are on the single UMC UM82C452. */ + device_add_inst(&ns16450_device, 1); + device_add_inst(&ns16450_device, 2); + + return ret; +} + + +static void +machine_at_scamp_common_init(const machine_t *model) +{ + machine_at_common_ide_init(model); + + device_add(&keyboard_ps2_ami_device); + device_add(&fdc_at_device); device_add(&vlsi_scamp_device); +} + + +const device_t * +at_commodore_sl386sx25_get_device(void) +{ + return &gd5402_onboard_device; +} + + +int +machine_at_commodore_sl386sx25_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/cbm_sl386sx25/f000.rom", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_scamp_common_init(model); if (gfxcard == VID_INTERNAL) device_add(&gd5402_onboard_device); @@ -490,6 +550,33 @@ machine_at_commodore_sl386sx_init(const machine_t *model) } +const device_t * +at_spc6033p_get_device(void) +{ + return &ati28800k_spc6033p_device; +} + + +int +machine_at_spc6033p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/spc6033p/phoenix.bin", + 0x000f0000, 65536, 0x10000); + + if (bios_only || !ret) + return ret; + + machine_at_scamp_common_init(model); + + if (gfxcard == VID_INTERNAL) + device_add(&ati28800k_spc6033p_device); + + return ret; +} + + int machine_at_awardsx_init(const machine_t *model) { diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 681e1674b..4a9ed91a5 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -157,12 +157,34 @@ machine_at_ecs386_init(const machine_t *model) machine_at_common_init(model); device_add(&cs8230_device); - device_add(&keyboard_at_ami_device); device_add(&fdc_at_device); + device_add(&keyboard_at_ami_device); return ret; } + +int +machine_at_spc6000a_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/spc6000a/3c80.u27", + L"roms/machines/spc6000a/9f80.u26", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 1); + device_add(&cs8230_device); + device_add(&fdc_at_device); + device_add(&keyboard_at_samsung_device); + + return ret; +} + + int machine_at_ustechnologies386_init(const machine_t *model) { @@ -183,6 +205,7 @@ machine_at_ustechnologies386_init(const machine_t *model) return ret; } + int machine_at_rycleopardlx_init(const machine_t *model) { @@ -224,6 +247,7 @@ machine_at_486vchd_init(const machine_t *model) return ret; } + int machine_at_cs4031_init(const machine_t *model) { @@ -243,6 +267,7 @@ machine_at_cs4031_init(const machine_t *model) return ret; } + int machine_at_pb410a_init(const machine_t *model) { @@ -269,6 +294,7 @@ machine_at_pb410a_init(const machine_t *model) return ret; } + #if defined(DEV_BRANCH) && defined(USE_VECT486VL) int machine_at_vect486vl_init(const machine_t *model) // has HDC problems @@ -294,6 +320,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems return ret; } + const device_t * at_vect486vl_get_device(void) { @@ -301,6 +328,7 @@ at_vect486vl_get_device(void) } #endif + int machine_at_acera1g_init(const machine_t *model) { @@ -325,6 +353,7 @@ machine_at_acera1g_init(const machine_t *model) return ret; } + const device_t * at_acera1g_get_device(void) { @@ -445,6 +474,7 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } + int machine_at_403tg_init(const machine_t *model) { @@ -466,6 +496,7 @@ machine_at_403tg_init(const machine_t *model) return ret; } + int machine_at_pc330_6571_init(const machine_t *model) // doesn't like every CPU other than the iDX4 and the Intel OverDrive, hangs without a PS/2 mouse { @@ -516,6 +547,7 @@ machine_at_ami471_init(const machine_t *model) return ret; } + int machine_at_vli486sv2g_init(const machine_t *model) { @@ -534,6 +566,7 @@ machine_at_vli486sv2g_init(const machine_t *model) return ret; } + int machine_at_dtk486_init(const machine_t *model) { @@ -891,6 +924,7 @@ machine_at_486vipio2_init(const machine_t *model) } #endif + #if defined(DEV_BRANCH) && defined(USE_M1489) int machine_at_abpb4_init(const machine_t *model) @@ -919,6 +953,7 @@ machine_at_abpb4_init(const machine_t *model) } #endif + #if defined(DEV_BRANCH) && defined(USE_STPC) int machine_at_itoxstar_init(const machine_t *model) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cadaf7f87..b1483da17 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -133,7 +133,7 @@ const machine_t machines[] = { { "[GC103] Quadtel 286 clone", "quadt286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_quadt286_init, NULL }, { "[GC103] Trigem 286M", "tg286m", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, { "[NEAT] AMI 286 clone", "ami286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, - { "[NEAT] NCR 3302", "ncr_3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_ncr3302_init, NULL }, + { "[NEAT] NCR 3302", "ncr_3302", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_VIDEO, 512, 16384, 128, 127, machine_at_ncr3302_init, NULL }, { "[NEAT] Phoenix 286 clone", "px286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_px286_init, NULL }, { "[SCAT] Award 286 clone", "award286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_award286_init, NULL }, { "[SCAT] GW-286CT GEAR", "gw286ct", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_gw286ct_init, NULL }, @@ -141,6 +141,7 @@ const machine_t machines[] = { { "[SCAT] Hyundai Super-286TR", "super286tr", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_super286tr_init, NULL }, { "[SCAT] Samsung SPC-4200P", "spc4200p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, { "[SCAT] Samsung SPC-4216P", "spc4216p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2, 1024, 5120,1024, 127, machine_at_spc4216p_init, NULL }, + { "[SCAT] Samsung SPC-4620P", "spc4620p", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_VIDEO, 1024, 5120,1024, 127, machine_at_spc4620p_init, NULL }, { "[SCAT] Samsung Deskmaster 286", "deskmaster286", MACHINE_TYPE_286, CPU_PKG_286, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_deskmaster286_init, NULL }, /* 286 machines that utilize the MCA bus */ @@ -156,9 +157,11 @@ const machine_t machines[] = { { "[HT18] AMA-932J", "ama932j", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, { "[Intel 82335] ADI 386SX", "adi386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_adi386sx_init, NULL }, { "[Intel 82335] Shuttle 386SX", "shuttle386sx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_shuttle386sx_init, NULL }, + { "[NEAT] Commodore SL386SX-16", "cbm_sl386sx16", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 8192, 512, 127, machine_at_commodore_sl386sx16_init, NULL }, { "[NEAT] DTK 386SX clone", "dtk386", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_init, NULL }, { "[OPTi 291] DTK PPM-3333P", "awardsx", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_awardsx_init, NULL }, - { "[SCAMP] Commodore SL386SX", "cbm_sl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device }, + { "[SCAMP] Commodore SL386SX-25", "cbm_sl386sx25", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 8192, 512, 127, machine_at_commodore_sl386sx25_init, at_commodore_sl386sx25_get_device }, + { "[SCAMP] Samsung SPC-6033P", "spc6033p", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 2048, 12288, 2048, 127, machine_at_spc6033p_init, at_spc6033p_get_device }, { "[SCAT] KMX-C-02", "kmxc02", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 512, 127, machine_at_kmxc02_init, NULL }, { "[WD76C10] Amstrad MegaPC", "megapc", MACHINE_TYPE_386SX, CPU_PKG_386SX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE | MACHINE_VIDEO, 1024, 32768, 1024, 127, machine_at_wd76c10_init, NULL }, @@ -167,7 +170,8 @@ const machine_t machines[] = { /* 386DX machines */ { "[ACC 2168] AMI 386DX clone", "acc386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_acc386_init, NULL }, - { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, + { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 1024, 16384, 1024, 127, machine_at_ecs386_init, NULL }, + { "[C&T 386] Samsung SPC-6000A", "spc6000a", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_spc6000a_init, NULL }, { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE | MACHINE_VIDEO, 1024, 14336, 1024, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, { "[SiS 310] ASUS ISA-386C", "asus386", MACHINE_TYPE_386DX, CPU_PKG_386DX, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT, 512, 16384, 128, 127, machine_at_asus386_init, NULL }, diff --git a/src/mem/mem.c b/src/mem/mem.c index 4c9d6a8c2..ae716718e 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -122,6 +122,7 @@ static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; static uint32_t _mem_state[MEM_MAPPINGS_NO]; +static uint32_t remap_start_addr; #ifdef ENABLE_MEM_LOG @@ -1976,8 +1977,7 @@ mem_write_raml(uint32_t addr, uint32_t val, void *priv) static uint8_t mem_read_remapped(uint32_t addr, void *priv) { - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) addreadlookup(mem_logical_addr, addr); return ram[addr]; @@ -1987,8 +1987,7 @@ mem_read_remapped(uint32_t addr, void *priv) static uint16_t mem_read_remappedw(uint32_t addr, void *priv) { - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) addreadlookup(mem_logical_addr, addr); return *(uint16_t *)&ram[addr]; @@ -1998,8 +1997,7 @@ mem_read_remappedw(uint32_t addr, void *priv) static uint32_t mem_read_remappedl(uint32_t addr, void *priv) { - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) addreadlookup(mem_logical_addr, addr); return *(uint32_t *)&ram[addr]; @@ -2010,8 +2008,7 @@ static void mem_write_remapped(uint32_t addr, uint8_t val, void *priv) { uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); @@ -2024,8 +2021,7 @@ static void mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) { uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) { addwritelookup(mem_logical_addr, addr); mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); @@ -2038,8 +2034,7 @@ static void mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) { uint32_t oldaddr = addr; - if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024))) - addr = 0xA0000 + (addr - (mem_size * 1024)); + addr = 0xA0000 + (addr - remap_start_addr); if (AT) { addwritelookup(mem_logical_addr, addr); mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); @@ -2693,14 +2688,12 @@ mem_reset(void) base_mapping = last_mapping = NULL; - memset(_mem_state, 0x00, sizeof(_mem_state)); + /* Set the entire memory space as external. */ + memset(_mem_state, 0x02, sizeof(_mem_state)); + /* Set the low RAM space as internal. */ mem_set_mem_state_both(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state_both(0x0a0000, 0x60000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - mem_set_mem_state_both((mem_size << 10), (uint32_t) (0x100000000ULL - (mem_size << 10)), - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, @@ -2802,6 +2795,8 @@ mem_remap_top(int kb) if (size > kb) size = kb; + remap_start_addr = start << 10; + for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { offset = c - ((start * 1024) >> 12); pages[c].mem = &ram[0xA0000 + (offset << 12)]; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 5dcca426a..da7fc4fcc 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -43,7 +43,12 @@ #endif #define BIOS_ATIKOR_PATH L"roms/video/ati28800/atikorvga.bin" +#define BIOS_ATIKOR_4620P_PATH_L L"roms/machines/spc4620p/31005h.u8" +#define BIOS_ATIKOR_4620P_PATH_H L"roms/machines/spc4620p/31005h.u10" +#define BIOS_ATIKOR_6033P_PATH L"roms/machines/spc6033p/phoenix.bin" #define FONT_ATIKOR_PATH L"roms/video/ati28800/ati_ksc5601.rom" +#define FONT_ATIKOR_4620P_PATH L"roms/machines/spc4620p/svb6120a_font.rom" +#define FONT_ATIKOR_6033P_PATH L"roms/machines/spc6033p/svb6120a_font.rom" #define BIOS_VGAXL_EVEN_PATH L"roms/video/ati28800/xleven.bin" #define BIOS_VGAXL_ODD_PATH L"roms/video/ati28800/xlodd.bin" @@ -80,7 +85,8 @@ typedef struct ati28800_t } ati28800_t; -static video_timings_t timing_ati28800 = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; +static video_timings_t timing_ati28800 = {VIDEO_ISA, 3, 3, 6, 5, 5, 10}; +static video_timings_t timing_ati28800_spc = {VIDEO_ISA, 2, 2, 4, 4, 4, 8}; #ifdef ENABLE_ATI28800_LOG @@ -459,9 +465,13 @@ ati28800k_init(const device_t *info) ati28800_t *ati28800 = (ati28800_t *) malloc(sizeof(ati28800_t)); memset(ati28800, 0, sizeof(ati28800_t)); - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800); - - ati28800->memory = device_get_config_int("memory"); + if (info->local == 0) { + ati28800->memory = device_get_config_int("memory"); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800); + } else { + ati28800->memory = 512; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati28800_spc); + } ati28800->port_03dd_val = 0; ati28800->get_korean_font_base = 0; @@ -471,8 +481,22 @@ ati28800k_init(const device_t *info) ati28800->in_get_korean_font_kind_set = 0; ati28800->ksc5601_mode_enabled = 0; - rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_PATH, 6); + switch(info->local) { + case 0: + default: + rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_PATH, 6); + break; + case 1: + rom_init_interleaved(&ati28800->bios_rom, BIOS_ATIKOR_4620P_PATH_L, BIOS_ATIKOR_4620P_PATH_H, 0xc0000, + 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_4620P_PATH, 6); + break; + case 2: + rom_init(&ati28800->bios_rom, BIOS_ATIKOR_6033P_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont(FONT_ATIKOR_6033P_PATH, 6); + break; + } svga_init(info, &ati28800->svga, ati28800, ati28800->memory << 10, /*Memory size, default 512KB*/ ati28800k_recalctimings, @@ -709,6 +733,28 @@ const device_t ati28800k_device = ati28800_config }; +const device_t ati28800k_spc4620p_device = +{ + "ATI Korean VGA On-Board SPC-4620P", + DEVICE_ISA, + 1, + ati28800k_init, ati28800_close, NULL, + { NULL }, + ati28800_speed_changed, + ati28800_force_redraw +}; + +const device_t ati28800k_spc6033p_device = +{ + "ATI Korean VGA On-Board SPC-6033P", + DEVICE_ISA, + 2, + ati28800k_init, ati28800_close, NULL, + { NULL }, + ati28800_speed_changed, + ati28800_force_redraw +}; + const device_t compaq_ati28800_device = { "Compaq ATI-28800", diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 96a4e13a1..d08863952 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -42,7 +42,7 @@ #define BIOS_GD5401_PATH L"roms/video/cirruslogic/avga1.rom" #define BIOS_GD5402_PATH L"roms/video/cirruslogic/avga2.rom" -#define BIOS_GD5402_ONBOARD_PATH L"roms/machines/cbm_sl386sx25/Commodore386SX-25_AVGA2.bin" +#define BIOS_GD5402_ONBOARD_PATH L"roms/machines/cbm_sl386sx25/c000.rom" #define BIOS_GD5420_PATH L"roms/video/cirruslogic/5420.vbi" #define BIOS_GD5422_PATH L"roms/video/cirruslogic/cl5422.bin" #define BIOS_GD5426_PATH L"roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" From dc5d3b9754168ec7b5c57f5affd0863cd9eb5bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= Date: Mon, 28 Dec 2020 14:06:16 +0100 Subject: [PATCH 44/60] Send actual delete on Ctrl+Alt+Del Fixes NT v1.196 --- src/pc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pc.c b/src/pc.c index cec907027..ef1005091 100644 --- a/src/pc.c +++ b/src/pc.c @@ -648,14 +648,14 @@ pc_init_modules(void) void -pc_send_ca(uint8_t sc) +pc_send_ca(uint16_t sc) { - keyboard_input(1, 29); /* Ctrl key pressed */ - keyboard_input(1, 56); /* Alt key pressed */ + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x38); /* Alt key pressed */ keyboard_input(1, sc); keyboard_input(0, sc); - keyboard_input(0, 56); /* Alt key released */ - keyboard_input(0, 29); /* Ctrl key released */ + keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ } @@ -663,7 +663,7 @@ pc_send_ca(uint8_t sc) void pc_send_cad(void) { - pc_send_ca(83); + pc_send_ca(0xE053); } From 0146761945a363f480365017cc80620399e04f33 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Tue, 29 Dec 2020 22:03:37 +0200 Subject: [PATCH 45/60] Implemented the LG Prime 3C SIO Some terrible Super I/O used in terrible motherboards. Good to have :b --- src/include/86box/machine.h | 1 + src/include/86box/sio.h | 2 + src/machine/m_at_socket7.c | 28 +++ src/machine/machine_table.c | 1 + src/sio/sio_prime3c.c | 339 ++++++++++++++++++++++++++++++++++++ src/win/Makefile.mingw | 1 + 6 files changed, 372 insertions(+) create mode 100644 src/sio/sio_prime3c.c diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 56ee11e66..b64e246d2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -419,6 +419,7 @@ extern int machine_at_p65up5_cp55t2d_init(const machine_t *); extern int machine_at_p55tvp4_init(const machine_t *); extern int machine_at_p55va_init(const machine_t *); extern int machine_at_i430vx_init(const machine_t *); +extern int machine_at_5ivg_init(const machine_t *); extern int machine_at_brio80xx_init(const machine_t *); extern int machine_at_8500tvxa_init(const machine_t *); extern int machine_at_presario4500_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index 3c4702ffa..afac7606e 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -44,6 +44,8 @@ extern const device_t pc87309_15c_device; extern const device_t pc87332_device; extern const device_t pc87332_ps1_device; extern const device_t pc97307_device; +extern const device_t prime3c_device; +extern const device_t prime3c_ide_device; extern const device_t ps1_m2133_sio; extern const device_t sio_detect_device; extern const device_t um8669f_device; diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 9e750c3c3..acdb2278e 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -580,6 +580,34 @@ machine_at_p55tvp4_init(const machine_t *model) return ret; } +int +machine_at_5ivg_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/5ivg/5IVG.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430vx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_pci_device); + device_add(&prime3c_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + int machine_at_i430vx_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b1483da17..05536c7e1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -309,6 +309,7 @@ const machine_t machines[] = { /* 430VX */ { "[i430VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55tvp4_init, NULL }, + { "[i430VX] Azza 5IVG", "5ivg", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_5ivg_init, NULL }, { "[i430VX] Biostar MB-8500TVX-A", "8500tvxa", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_8500tvxa_init, NULL }, { "[i430VX] Compaq Presario 4500", "presario4500", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_VIDEO, 8192, 131072, 8192, 127, machine_at_presario4500_init, NULL }, { "[i430VX] Epox P55-VA", "p55va", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p55va_init, NULL }, diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c new file mode 100644 index 000000000..5daa51e2b --- /dev/null +++ b/src/sio/sio_prime3c.c @@ -0,0 +1,339 @@ +/* + * 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. + * + * Emulation of the LG Prime3C Super I/O + * + * Authors: Tiseno100 + * Copyright 2020 Tiseno100 + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#ifdef ENABLE_PRIME3C_LOG +int prime3c_do_log = ENABLE_PRIME3C_LOG; +static void +prime3c_log(const char *fmt, ...) +{ + va_list ap; + + if (prime3c_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define prime3c_log(fmt, ...) +#endif + +/* Function Select(Note on prime3c_enable) */ +#define FUNCTION_SELECT dev->regs[0xc2] + +/* Base Address Registers */ +#define FDC_BASE_ADDRESS dev->regs[0xc3] +#define IDE_BASE_ADDRESS dev->regs[0xc4] +#define IDE_SIDE_ADDRESS dev->regs[0xc5] +#define LPT_BASE_ADDRESS dev->regs[0xc6] +#define UART1_BASE_ADDRESS dev->regs[0xc7] +#define UART2_BASE_ADDRESS dev->regs[0xc8] + +/* FDC/LPT Configuration */ +#define FDC_LPT_DMA dev->regs[0xc9] +#define FDC_LPT_IRQ dev->regs[0xca] + +/* UART 1/2 Configuration */ +#define UART_IRQ dev->regs[0xcb] + +/* Miscellaneous Configuration*/ +#define FDC_SWAP (dev->regs[0xd6] & 0x01) + +/* IDE functionality(Note on Init) */ +#define HAS_IDE_FUNCTIONALITY dev->ide_function + +typedef struct +{ + uint8_t index, regs[256], cfg_lock, ide_function; + + fdc_t *fdc_controller; + serial_t *uart[2]; + +} prime3c_t; + +void prime3c_fdc_handler(prime3c_t *dev); +void prime3c_uart_handler(uint8_t num, prime3c_t *dev); +void prime3c_lpt_handler(prime3c_t *dev); +void prime3c_ide_handler(prime3c_t *dev); +void prime3c_enable(prime3c_t *dev); + +static void +prime3c_write(uint16_t addr, uint8_t val, void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + switch (addr) + { + case 0x398: + dev->index = val; + + /* Enter/Escape Configuration Mode */ + if (val == 0x33) + dev->cfg_lock = 0; + else if (val == 0x55) + dev->cfg_lock = 1; + break; + + case 0x399: + if (!dev->cfg_lock) + { + switch (dev->index) + { + case 0xc2: + FUNCTION_SELECT = val & 0xbf; + prime3c_enable(dev); + break; + + case 0xc3: + FDC_BASE_ADDRESS = val & 0xfc; + prime3c_fdc_handler(dev); + break; + + case 0xc4: + IDE_BASE_ADDRESS = val & 0xfc; + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + break; + + case 0xc5: + IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02; + prime3c_ide_handler(dev); + break; + + case 0xc6: + LPT_BASE_ADDRESS = val; + break; + + case 0xc7: + UART1_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(0, dev); + break; + + case 0xc8: + UART2_BASE_ADDRESS = val & 0xfe; + prime3c_uart_handler(1, dev); + break; + + case 0xc9: + FDC_LPT_DMA = val; + prime3c_fdc_handler(dev); + break; + + case 0xca: + FDC_LPT_IRQ = val; + prime3c_fdc_handler(dev); + prime3c_lpt_handler(dev); + break; + + case 0xcb: + UART_IRQ = val; + prime3c_uart_handler(0, dev); + prime3c_uart_handler(1, dev); + break; + + case 0xcd: + case 0xce: + dev->regs[dev->index] = val; + break; + + case 0xcf: + dev->regs[dev->index] = val & 0x3f; + break; + + case 0xd0: + dev->regs[dev->index] = val & 0xfc; + break; + + case 0xd1: + dev->regs[dev->index] = val & 0x3f; + break; + + case 0xd3: + dev->regs[dev->index] = val & 0x7c; + break; + + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + dev->regs[dev->index] = val; + break; + } + } + break; + } +} + +static uint8_t +prime3c_read(uint16_t addr, void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + return dev->regs[addr]; +} + +void prime3c_fdc_handler(prime3c_t *dev) +{ + fdc_remove(dev->fdc_controller); + if (FUNCTION_SELECT & 0x10) + { + fdc_set_base(dev->fdc_controller, FDC_BASE_ADDRESS << 2); + fdc_set_irq(dev->fdc_controller, (FDC_LPT_IRQ >> 4) & 0xf); + fdc_set_dma_ch(dev->fdc_controller, (FDC_LPT_DMA >> 4) & 0xf); + fdc_set_swap(dev->fdc_controller, FDC_SWAP); + prime3c_log("Prime3C-FDC: BASE %04x IRQ %01x DMA %01x\n", FDC_BASE_ADDRESS << 2, (FDC_LPT_IRQ >> 4) & 0xf, (FDC_LPT_DMA >> 4) & 0xf); + } +} + +void prime3c_uart_handler(uint8_t num, prime3c_t *dev) +{ + serial_remove(dev->uart[num & 1]); + if (FUNCTION_SELECT & (!(num & 1) ? 0x04 : 0x08)) + { + serial_setup(dev->uart[num & 1], (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); + prime3c_log("Prime3C-UART%01x: BASE %04x IRQ %01x\n", num & 1, (!(num & 1) ? UART1_BASE_ADDRESS : UART2_BASE_ADDRESS) << 2, (UART_IRQ >> (!(num & 1) ? 4 : 0)) & 0xf); + } +} + +void prime3c_lpt_handler(prime3c_t *dev) +{ + lpt1_remove(); + if (!(FUNCTION_SELECT & 0x03)) + { + + lpt1_init(LPT_BASE_ADDRESS << 2); + lpt1_irq(FDC_LPT_IRQ & 0xf); + prime3c_log("Prime3C-LPT: BASE %04x IRQ %02x\n", LPT_BASE_ADDRESS << 2, FDC_LPT_IRQ & 0xf); + } +} + +void prime3c_ide_handler(prime3c_t *dev) +{ + ide_pri_disable(); + if (FUNCTION_SELECT & 0x20) + { + ide_set_base(0, IDE_BASE_ADDRESS << 2); + ide_set_side(0, IDE_SIDE_ADDRESS << 2); + ide_pri_enable(); + prime3c_log("Prime3C-IDE: BASE %04x SIDE %04x\n", IDE_BASE_ADDRESS << 2, IDE_SIDE_ADDRESS << 2); + } +} + +void prime3c_enable(prime3c_t *dev) +{ +/* +Simulate a device enable/disable scenario + +Register C2: Function Select +Bit 7: Gameport +Bit 6: Reserved +Bit 5: IDE +Bit 4: FDC +Bit 3: UART 2 +Bit 2: UART 1 +Bit 1/0: PIO (0/0 Unidirectional , 0/1 ECP, 1/0 EPP, 1/1 Disabled) + +Note: 86Box LPT is simplistic and can't do ECP or EPP. +*/ + +!(FUNCTION_SELECT & 0x03) ? prime3c_lpt_handler(dev) : lpt1_remove(); +(FUNCTION_SELECT & 0x04) ? prime3c_uart_handler(0, dev) : serial_remove(dev->uart[0]); +(FUNCTION_SELECT & 0x08) ? prime3c_uart_handler(1, dev) : serial_remove(dev->uart[1]); +(FUNCTION_SELECT & 0x10) ? prime3c_fdc_handler(dev) : fdc_remove(dev->fdc_controller); +if (HAS_IDE_FUNCTIONALITY) + (FUNCTION_SELECT & 0x20) ? prime3c_ide_handler(dev) : ide_pri_disable(); +} + +static void +prime3c_close(void *priv) +{ + prime3c_t *dev = (prime3c_t *)priv; + + free(dev); +} + +static void * +prime3c_init(const device_t *info) +{ + prime3c_t *dev = (prime3c_t *)malloc(sizeof(prime3c_t)); + memset(dev, 0, sizeof(prime3c_t)); + + /* Avoid conflicting with machines that make no use of the Prime3C Internal IDE */ + HAS_IDE_FUNCTIONALITY = info->local; + + dev->regs[0xc0] = 0x3c; + dev->regs[0xc2] = 0x03; + dev->regs[0xc3] = 0x3c; + dev->regs[0xc4] = 0x3c; + dev->regs[0xc5] = 0x3d; + dev->regs[0xd5] = 0x3c; + + dev->fdc_controller = device_add(&fdc_at_device); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + if (HAS_IDE_FUNCTIONALITY) + device_add(&ide_isa_device); + + prime3c_fdc_handler(dev); + prime3c_uart_handler(0, dev); + prime3c_uart_handler(1, dev); + prime3c_lpt_handler(dev); + if (HAS_IDE_FUNCTIONALITY) + prime3c_ide_handler(dev); + + io_sethandler(0x0398, 0x0002, prime3c_read, NULL, NULL, prime3c_write, NULL, NULL, dev); + + return dev; +} + +const device_t prime3c_device = { + "Goldstar Prime3C", + 0, + 0, + prime3c_init, + prime3c_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t prime3c_ide_device = { + "Goldstar Prime3C with IDE functionality", + 0, + 1, + prime3c_init, + prime3c_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 78977a784..d0d24f36e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -641,6 +641,7 @@ SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87332.o \ + sio_prime3c.o \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \ From 7268bfa06dca221df5a85bb61b408995b92bae42 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 30 Dec 2020 22:37:51 +0200 Subject: [PATCH 46/60] Added the Vectra VEi8 A 686 Vectra using the Award BIOS --- src/include/86box/machine.h | 1 + src/include/86box/sio.h | 2 ++ src/machine/m_at_slot1.c | 30 ++++++++++++++++++++++++++++++ src/machine/machine_table.c | 1 + src/sio/sio_prime3c.c | 2 +- src/win/Makefile.mingw | 2 +- 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b64e246d2..676e36c75 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -490,6 +490,7 @@ extern int machine_at_ergox365_init(const machine_t *); extern int machine_at_ficka6130_init(const machine_t *); extern int machine_at_p3v133_init(const machine_t *); extern int machine_at_p3v4x_init(const machine_t *); +extern int machine_at_vei8_init(const machine_t *); #ifdef EMU_DEVICE_H extern const device_t *at_tsunamiatx_get_device(void); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index afac7606e..e6e4cbb10 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -32,6 +32,8 @@ extern const device_t fdc37c931apm_compaq_device; extern const device_t fdc37c932fr_device; extern const device_t fdc37c932qf_device; extern const device_t fdc37c935_device; +extern const device_t fdc37m60x_device; +extern const device_t fdc37m60x_370_device; extern const device_t i82091aa_device; extern const device_t i82091aa_398_device; extern const device_t i82091aa_ide_device; diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index ebdc421b1..202f975ff 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -622,3 +622,33 @@ machine_at_p3v4x_init(const machine_t *model) return ret; } + +int +machine_at_vei8_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/vei8/QHW1001.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&fdc37m60x_370_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x3, 512); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 05536c7e1..64545a0ba 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -374,6 +374,7 @@ const machine_t machines[] = { { "[i440BX] ABIT BF6", "bf6", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 133333333, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_bf6_init, NULL }, { "[i440BX] AOpen AX6BC", "ax6bc", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_ax6bc_init, NULL }, { "[i440BX] Gigabyte GA-686BX", "686bx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_686bx_init, NULL }, + { "[i440BX] HP Vectra VEi 8", "vei8", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 5.5, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vei8_init, NULL }, { "[i440BX] Tyan Tsunami ATX", "tsunamiatx", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 112121212, 1800, 3500, 3.5, 5.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 8192,1048576, 8192, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device }, { "[i440BX] SuperMicro Super P6SBA", "p6sba", MACHINE_TYPE_SLOT1, CPU_PKG_SLOT1, 0, 66666667, 100000000, 1800, 3500, 3.0, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 786432, 8192, 255, machine_at_p6sba_init, NULL }, #if defined(DEV_BRANCH) && defined(NO_SIO) diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index 5daa51e2b..2e0b688a3 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -197,7 +197,7 @@ prime3c_read(uint16_t addr, void *priv) { prime3c_t *dev = (prime3c_t *)priv; - return dev->regs[addr]; + return dev->regs[dev->index]; } void prime3c_fdc_handler(prime3c_t *dev) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index d0d24f36e..a73be16b4 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -639,7 +639,7 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ - sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ + sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87332.o \ sio_prime3c.o \ sio_w83787f.o \ From 2566d15a4c328c6433df8a12dbd7f9f33435b912 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Wed, 30 Dec 2020 22:39:25 +0200 Subject: [PATCH 47/60] Added the missing FDC37M60x Super I/O For the Vectra VEi8 implementation --- src/sio/sio_fdc37m60x.c | 321 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 src/sio/sio_fdc37m60x.c diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c new file mode 100644 index 000000000..ca0111405 --- /dev/null +++ b/src/sio/sio_fdc37m60x.c @@ -0,0 +1,321 @@ +/* + * 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. + * + * Emulation of the SMSC FDC37M60x Super I/O + * + * Authors: Tiseno100 + * Copyright 2020 Tiseno100 + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#define SIO_INDEX_PORT dev->sio_index_port +#define INDEX dev->index + +/* Current Logical Device Number */ +#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] + +/* Global Device Configuration */ +#define ENABLED dev->device_regs[CURRENT_LOGICAL_DEVICE][0x30] +#define BASE_ADDRESS ((dev->device_regs[CURRENT_LOGICAL_DEVICE][0x60] << 8) | (dev->device_regs[CURRENT_LOGICAL_DEVICE][0x61])) +#define IRQ dev->device_regs[CURRENT_LOGICAL_DEVICE][0x70] +#define DMA dev->device_regs[CURRENT_LOGICAL_DEVICE][0x74] + +/* Miscellaneous Chip Functionality */ +#define SOFT_RESET (val & 0x01) +#define POWER_CONTROL dev->regs[0x22] + +#ifdef ENABLE_FDC37M60X_LOG +int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG; +static void +fdc37m60x_log(const char *fmt, ...) +{ + va_list ap; + + if (fdc37m60x_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define fdc37m60x_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function; + uint16_t sio_index_port; + + fdc_t *fdc_controller; + serial_t *uart[2]; + +} fdc37m60x_t; + +void fdc37m60x_fdc_handler(fdc37m60x_t *dev); +void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); +void fdc37m60x_lpt_handler(fdc37m60x_t *dev); +void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); +static void fdc37m60x_reset(void *priv); + +static void +fdc37m60x_write(uint16_t addr, uint8_t val, void *priv) +{ + fdc37m60x_t *dev = (fdc37m60x_t *)priv; + + switch (addr) + { + case 0x3f0: + case 0x370: + INDEX = val; + + /* Enter/Escape Configuration Mode */ + if (val == 0x55) + dev->cfg_lock = 0; + else if (val == 0xaa) + dev->cfg_lock = 1; + break; + + case 0x3f1: + case 0x371: + if (!dev->cfg_lock) + { + switch (INDEX) + { + /* Global Configuration */ + case 0x02: + dev->regs[INDEX] = val; + if (SOFT_RESET) + fdc37m60x_reset(dev); + break; + + case 0x07: + CURRENT_LOGICAL_DEVICE = (val & 0x0f); + break; + + case 0x22: + POWER_CONTROL = val & 0x3f; + break; + + case 0x23: + dev->regs[INDEX] = val & 0x3f; + break; + + case 0x24: + dev->regs[INDEX] = val & 0xce; + break; + + /* Device Configuration */ + case 0x30: + case 0x60: + case 0x61: + case 0x70: + case 0x74: + if(CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ + dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; + fdc37m60x_logical_device_handler(dev); + break; + } + } + break; + } +} + +static uint8_t +fdc37m60x_read(uint16_t addr, void *priv) +{ + fdc37m60x_t *dev = (fdc37m60x_t *)priv; + + return (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; +} + +void fdc37m60x_fdc_handler(fdc37m60x_t *dev) +{ + fdc_remove(dev->fdc_controller); + if(ENABLED || (POWER_CONTROL & 0x01)) + { + fdc_set_base(dev->fdc_controller, BASE_ADDRESS); + fdc_set_irq(dev->fdc_controller, IRQ & 0xf); + fdc_set_dma_ch(dev->fdc_controller, DMA & 0x07); + fdc37m60x_log("SMC60x-FDC: BASE %04x IRQ %d DMA %d\n", BASE_ADDRESS, IRQ & 0xf, DMA & 0x07); + } +} + +void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev) +{ + serial_remove(dev->uart[num & 1]); + if(!(num & 1) ? (ENABLED || (POWER_CONTROL & 0x10)) : (ENABLED || (POWER_CONTROL & 0x20))) + { + serial_setup(dev->uart[num & 1], BASE_ADDRESS, IRQ & 0xf); + fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS, IRQ & 0xf); + } +} + +void fdc37m60x_lpt_handler(fdc37m60x_t *dev) +{ + lpt1_remove(); + if(ENABLED || (POWER_CONTROL & 0x80)) + { + lpt1_init(BASE_ADDRESS); + lpt1_irq(IRQ & 0xf); + fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS, IRQ & 0xf); + } +} + +void fdc37m60x_logical_device_handler(fdc37m60x_t *dev) +{ +/* +Register 07h: +Device 0: FDC +Device 3: LPT +Device 4: UART1 +Device 5: UART2 +*/ + switch (CURRENT_LOGICAL_DEVICE) + { + case 0x00: + fdc37m60x_fdc_handler(dev); + break; + + case 0x03: + fdc37m60x_lpt_handler(dev); + break; + + case 0x04: + fdc37m60x_uart_handler(0, dev); + break; + + case 0x05: + fdc37m60x_uart_handler(1, dev); + break; + } +} + +static void +fdc37m60x_reset(void *priv) +{ + fdc37m60x_t *dev = (fdc37m60x_t *)priv; + + CURRENT_LOGICAL_DEVICE = 0x00; + dev->regs[0x22] = 0x00; + dev->regs[0x26] = SIO_INDEX_PORT & 0xf; + dev->regs[0x27] = (SIO_INDEX_PORT >> 4) & 0xf; + + /* FDC Registers */ + dev->device_regs[0][0x30] = 0x00; + dev->device_regs[0][0x60] = 0x03; /* Base Address */ + dev->device_regs[0][0x61] = 0xf0; + + dev->device_regs[0][0x70] = 0x06; + dev->device_regs[0][0x74] = 0x02; + + /* LPT Port */ + dev->device_regs[3][0x30] = 0x00; + dev->device_regs[3][0x60] = 0x00; /* Base Address */ + dev->device_regs[3][0x61] = 0x00; + + dev->device_regs[3][0x64] = 0x04; + + /* UART1 */ + dev->device_regs[4][0x30] = 0x00; + dev->device_regs[4][0x60] = 0x00; /* Base Address */ + dev->device_regs[4][0x61] = 0x00; + + dev->device_regs[4][0x70] = 0x00; + + /* UART2 */ + dev->device_regs[5][0x30] = 0x00; + dev->device_regs[5][0x60] = 0x00; /* Base Address */ + dev->device_regs[5][0x61] = 0x00; + + dev->device_regs[5][0x70] = 0x00; + + /* AUX */ + dev->device_regs[8][0x30] = 0x00; + + fdc37m60x_fdc_handler(dev); + fdc37m60x_uart_handler(0, dev); + fdc37m60x_uart_handler(1, dev); + fdc37m60x_lpt_handler(dev); +} + +static void +fdc37m60x_close(void *priv) +{ + fdc37m60x_t *dev = (fdc37m60x_t *)priv; + + free(dev); +} + +static void * +fdc37m60x_init(const device_t *info) +{ + fdc37m60x_t *dev = (fdc37m60x_t *)malloc(sizeof(fdc37m60x_t)); + memset(dev, 0, sizeof(fdc37m60x_t)); + SIO_INDEX_PORT = info->local; + + dev->regs[0x20] = 0x47; + dev->regs[0x24] = 0x04; + dev->device_regs[0][0xf0] = 0x0e; + dev->device_regs[0][0xf2] = 0xff; + dev->device_regs[3][0xf0] = 0x3c; + dev->device_regs[4][0xf1] = 0x02; + dev->device_regs[4][0xf2] = 0x03; + dev->device_regs[8][0xc0] = 0x06; + dev->device_regs[8][0xc1] = 0x03; + + dev->fdc_controller = device_add(&fdc_at_smc_device); + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + io_sethandler(SIO_INDEX_PORT, 0x0002, fdc37m60x_read, NULL, NULL, fdc37m60x_write, NULL, NULL, dev); + + return dev; +} + +const device_t fdc37m60x_device = { + "SMSC FDC37M60X", + 0, + 0x03f0, + fdc37m60x_init, + fdc37m60x_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t fdc37m60x_370_device = { + "SMSC FDC37M60X with 10K Pull Up Resistor", + 0, + 0x0370, + fdc37m60x_init, + fdc37m60x_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; From 5d7ea72881391063953ce87f965719475226988d Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Thu, 31 Dec 2020 21:49:47 +0200 Subject: [PATCH 48/60] Added the Mylex MVI486 A 486 Industrial board using the Mylex BIOS --- src/include/86box/machine.h | 1 + src/include/86box/sio.h | 2 + src/machine/m_at_386dx_486.c | 22 ++- src/machine/machine_table.c | 1 + src/sio/sio_pc87311.c | 297 +++++++++++++++++++++++++++++++++++ src/sio/sio_prime3c.c | 2 + src/win/Makefile.mingw | 2 +- 7 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 src/sio/sio_pc87311.c diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 676e36c75..31baeee20 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -309,6 +309,7 @@ extern int machine_at_vect486vl_init(const machine_t *); extern int machine_at_403tg_init(const machine_t *); extern int machine_at_pc330_6571_init(const machine_t *); +extern int machine_at_mvi486_init(const machine_t *); extern int machine_at_sis401_init(const machine_t *); extern int machine_at_av4_init(const machine_t *); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index e6e4cbb10..81dc8976e 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -43,6 +43,8 @@ extern const device_t pc87307_15c_device; extern const device_t pc87307_both_device; extern const device_t pc87309_device; extern const device_t pc87309_15c_device; +extern const device_t pc87311_device; +extern const device_t pc87311_ide_device; extern const device_t pc87332_device; extern const device_t pc87332_ps1_device; extern const device_t pc97307_device; diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 4a9ed91a5..e040e3128 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -474,7 +474,6 @@ machine_at_opti495_mr_init(const machine_t *model) return ret; } - int machine_at_403tg_init(const machine_t *model) { @@ -519,6 +518,27 @@ machine_at_pc330_6571_init(const machine_t *model) // doesn't like every CPU oth return ret; } +int +machine_at_mvi486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/mvi486/MVI627.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti895_device); + + device_add(&keyboard_at_device); + device_add(&pc87311_ide_device); + + return ret; +} + static void machine_at_sis_85c471_common_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 64545a0ba..cbad9c07c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -200,6 +200,7 @@ const machine_t machines[] = { { "[OPTi 495] MR 486 clone", "mr486", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 32768, 1024, 127, machine_at_opti495_mr_init, NULL }, { "[OPTi 802G] IBM PC 330 (type 6571)", "pc330_6571", MACHINE_TYPE_486, CPU_PKG_SOCKET3_PC330, 0, 25000000, 33333333, 0, 0, 2.0, 3.0, MACHINE_VLB | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_pc330_6571_init, NULL }, { "[OPTi 895] Jetway J-403TG", "403tg", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB, 1024, 65536, 1024, 127, machine_at_403tg_init, NULL }, + { "[OPTi 895] Mylex MVI486", "mvi486", MACHINE_TYPE_486, CPU_PKG_SOCKET1, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE_DUAL, 1024, 65536, 1024, 127, machine_at_mvi486_init, NULL }, { "[SiS 401] AMI 486 Clone", "sis401", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_sis401_init, NULL }, { "[SiS 460] ABIT AV4", "av4", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_VLB | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_av4_init, NULL }, { "[SiS 461] IBM PS/ValuePoint 433DX/Si", "valuepoint433", MACHINE_TYPE_486, CPU_PKG_SOCKET3, 0, 0, 0, 0, 0, 0, 0, MACHINE_AT | MACHINE_BUS_PS2 | MACHINE_IDE, 1024, 65536, 1024, 127, machine_at_valuepoint433_init, NULL }, diff --git a/src/sio/sio_pc87311.c b/src/sio/sio_pc87311.c new file mode 100644 index 000000000..2fff65d6c --- /dev/null +++ b/src/sio/sio_pc87311.c @@ -0,0 +1,297 @@ +/* + * 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. + * + * Emulation of the National Semiconductor PC87311 Super I/O + * + * Authors: Tiseno100 + * Copyright 2020 Tiseno100 + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/serial.h> +#include <86box/hdc.h> +#include <86box/hdc_ide.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/sio.h> + +#define HAS_IDE_FUNCTIONALITY dev->ide_function + +/* Basic Functionalities */ +#define FUNCTION_ENABLE dev->regs[0x00] +#define FUNCTION_ADDRESS dev->regs[0x01] +#define POWER_TEST dev->regs[0x02] + +/* Base Addresses */ +#define LPT_BA (FUNCTION_ADDRESS & 0x03) +#define UART1_BA ((FUNCTION_ADDRESS >> 2) & 0x03) +#define UART2_BA ((FUNCTION_ADDRESS >> 4) & 0x03) +#define COM_BA ((FUNCTION_ADDRESS >> 6) & 0x03) + +#ifdef ENABLE_PC87311_LOG +int pc87311_do_log = ENABLE_PC87311_LOG; +static void +pc87311_log(const char *fmt, ...) +{ + va_list ap; + + if (pc87311_do_log) + { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define pc87311_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, regs[256], cfg_lock, ide_function; + uint16_t base, irq; + fdc_t *fdc_controller; + serial_t *uart[2]; + +} pc87311_t; + +void pc87311_fdc_handler(pc87311_t *dev); +void pc87311_uart_handler(uint8_t num, pc87311_t *dev); +void pc87311_lpt_handler(pc87311_t *dev); +void pc87311_ide_handler(pc87311_t *dev); +void pc87311_enable(pc87311_t *dev); + +static void +pc87311_write(uint16_t addr, uint8_t val, void *priv) +{ + pc87311_t *dev = (pc87311_t *)priv; + + switch (addr) + { + case 0x398: + case 0x26e: + dev->index = val; + break; + + case 0x399: + case 0x26f: + switch (dev->index) + { + case 0x00: + FUNCTION_ENABLE = val; + break; + case 0x01: + FUNCTION_ADDRESS = val; + break; + case 0x02: + POWER_TEST = val; + break; + } + break; + } + + pc87311_enable(dev); +} + +static uint8_t +pc87311_read(uint16_t addr, void *priv) +{ + pc87311_t *dev = (pc87311_t *)priv; + + return dev->regs[dev->index]; +} + +void pc87311_fdc_handler(pc87311_t *dev) +{ + fdc_remove(dev->fdc_controller); + fdc_set_base(dev->fdc_controller, (FUNCTION_ENABLE & 0x20) ? 0x0370 : 0x03f0); + pc87311_log("PC87311-FDC: BASE %04x\n", (FUNCTION_ENABLE & 0x20) ? 0x0370 : 0x03f0); +} + +uint16_t com3(pc87311_t *dev) +{ + switch (COM_BA) + { + case 0: + return 0x03e8; + case 1: + return 0x0338; + case 2: + return 0x02e8; + case 3: + return 0x0220; + default: + return 0x03e8; + } +} + +uint16_t com4(pc87311_t *dev) +{ + switch (COM_BA) + { + case 0: + return 0x02e8; + case 1: + return 0x0238; + case 2: + return 0x02e0; + case 3: + return 0x0228; + default: + return 0x02e8; + } +} + +void pc87311_uart_handler(uint8_t num, pc87311_t *dev) +{ + serial_remove(dev->uart[num & 1]); + + switch ((!num & 1) ? UART1_BA : UART2_BA) + { + case 0: + dev->base = 0x03f8; + dev->irq = 4; + break; + case 1: + dev->base = 0x02f8; + dev->irq = 3; + break; + case 2: + dev->base = com3(dev); + dev->irq = 4; + break; + case 3: + dev->base = com4(dev); + dev->irq = 3; + break; + } + serial_setup(dev->uart[num & 1], dev->base, dev->irq); + pc87311_log("PC87311-UART%01x: BASE %04x IRQ %01x\n", num & 1, dev->base, dev->irq); +} + +void pc87311_lpt_handler(pc87311_t *dev) +{ + lpt1_remove(); + switch (LPT_BA) + { + case 0: + dev->base = 0x0378; + dev->irq = (POWER_TEST & 0x08) ? 7 : 5; + break; + case 1: + dev->base = 0x03bc; + dev->irq = 7; + break; + case 2: + dev->base = 0x0278; + dev->irq = 5; + break; + } + lpt1_init(dev->base); + lpt1_irq(dev->irq); + pc87311_log("PC87311-LPT: BASE %04x IRQ %01x\n", dev->base, dev->irq); +} + +void pc87311_ide_handler(pc87311_t *dev) +{ + ide_pri_disable(); + ide_sec_disable(); + + ide_set_base(0, 0x1f0); + ide_set_side(0, 0x3f6); + ide_pri_enable(); + + if (FUNCTION_ENABLE & 0x80) + { + ide_set_base(1, 0x170); + ide_set_side(1, 0x376); + ide_sec_enable(); + } + pc87311_log("PC87311-IDE: PRI %01x SEC %01x\n", (FUNCTION_ENABLE >> 6) & 1, (FUNCTION_ENABLE >> 7) & 1); +} + +void pc87311_enable(pc87311_t *dev) +{ + (FUNCTION_ENABLE & 0x01) ? pc87311_lpt_handler(dev) : lpt1_remove(); + (FUNCTION_ENABLE & 0x02) ? pc87311_uart_handler(0, dev) : serial_remove(dev->uart[0]); + (FUNCTION_ENABLE & 0x04) ? pc87311_uart_handler(1, dev) : serial_remove(dev->uart[1]); + (FUNCTION_ENABLE & 0x08) ? pc87311_fdc_handler(dev) : fdc_remove(dev->fdc_controller); + if (FUNCTION_ENABLE & 0x20) + pc87311_fdc_handler(dev); + if (HAS_IDE_FUNCTIONALITY) + { + (FUNCTION_ENABLE & 0x40) ? pc87311_ide_handler(dev) : ide_pri_disable(); + (FUNCTION_ADDRESS & 0x80) ? pc87311_ide_handler(dev) : ide_sec_disable(); + } +} + +static void +pc87311_close(void *priv) +{ + pc87311_t *dev = (pc87311_t *)priv; + + free(dev); +} + +static void * +pc87311_init(const device_t *info) +{ + pc87311_t *dev = (pc87311_t *)malloc(sizeof(pc87311_t)); + memset(dev, 0, sizeof(pc87311_t)); + + /* Avoid conflicting with machines that make no use of the PC87311 Internal IDE */ + HAS_IDE_FUNCTIONALITY = info->local; + + dev->fdc_controller = device_add(&fdc_at_nsc_device); + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + + if (HAS_IDE_FUNCTIONALITY) + device_add(&ide_isa_2ch_device); + + io_sethandler(0x0398, 0x0002, pc87311_read, NULL, NULL, pc87311_write, NULL, NULL, dev); + io_sethandler(0x026e, 0x0002, pc87311_read, NULL, NULL, pc87311_write, NULL, NULL, dev); + + pc87311_enable(dev); + + return dev; +} + +const device_t pc87311_device = { + "National Semiconductor PC87311", + 0, + 0, + pc87311_init, + pc87311_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; + +const device_t pc87311_ide_device = { + "National Semiconductor PC87311 with IDE functionality", + 0, + 1, + pc87311_init, + pc87311_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; diff --git a/src/sio/sio_prime3c.c b/src/sio/sio_prime3c.c index 2e0b688a3..b18e274fa 100644 --- a/src/sio/sio_prime3c.c +++ b/src/sio/sio_prime3c.c @@ -11,11 +11,13 @@ * Authors: Tiseno100 * Copyright 2020 Tiseno100 */ +#include #include #include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> #include <86box/timer.h> diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a73be16b4..46f5d619a 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -640,7 +640,7 @@ DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm SIOOBJ := sio_acc3221.o \ sio_f82c710.o sio_82091aa.o \ sio_fdc37c661.o sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o sio_fdc37m60x.o \ - sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87332.o \ + sio_pc87306.o sio_pc87307.o sio_pc87309.o sio_pc87311.o sio_pc87332.o \ sio_prime3c.o \ sio_w83787f.o \ sio_w83877f.o sio_w83977f.o \ From 9b9f2d7c7c379eefd3c09a846b9c193d38cc4fce Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:07:39 +0200 Subject: [PATCH 49/60] Properly implemented the ACC 2046/2168 Based on the ACC 2046 datasheet. 2168 is just the Green variation of it. --- src/chipset/acc2168.c | 148 +++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 39 deletions(-) diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 5461cb71a..66783022e 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -6,13 +6,15 @@ * * This file is part of the 86Box distribution. * - * Implementation of the ACC 2168 chipset + * Implementation of the ACC 2046/2168 chipset * * * * Authors: Sarah Walker, + * Tiseno100 * * Copyright 2019 Sarah Walker. + * Copyright 2021 Tiseno100. */ #include #include @@ -28,84 +30,152 @@ #include <86box/port_92.h> #include <86box/chipset.h> -#define enabled_shadow (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) -#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) +#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16))) +#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) +#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) typedef struct acc2168_t { - int reg_idx; - uint8_t regs[256]; + uint8_t reg_idx, regs[256]; } acc2168_t; -static void +static void acc2168_shadow_recalc(acc2168_t *dev) { -mem_set_mem_state_both(0xc0000, 0x8000, ((dev->regs[0x02] & 0x01) ? enabled_shadow : disabled_shadow)); -mem_set_mem_state_both(0xc8000, 0x8000, ((dev->regs[0x02] & 0x02) ? enabled_shadow : disabled_shadow)); -mem_set_mem_state_both(0xd0000, 0x10000, ((dev->regs[0x02] & 0x04) ? enabled_shadow : disabled_shadow)); -mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[0x02] & 0x08) ? enabled_shadow : disabled_shadow)); -mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[0x02] & 0x10) ? enabled_shadow : disabled_shadow)); + for (uint32_t i = 0; i < 5; i++) + mem_set_mem_state_both(SHADOW_ADDR, SHADOW_SIZE, SHADOW_RECALC); } -static void +static void acc2168_write(uint16_t addr, uint8_t val, void *p) { acc2168_t *dev = (acc2168_t *)p; - if (!(addr & 1)) - dev->reg_idx = val; - else { - dev->regs[dev->reg_idx] = val; + switch (addr) + { + case 0xf2: + dev->reg_idx = val; + break; + case 0xf3: + pclog("dev->regs[%02x] = %02x\n", dev->reg_idx, val); + switch (dev->reg_idx) + { + case 0x00: + dev->regs[dev->reg_idx] = val; + break; - switch (dev->reg_idx) { - case 0x02: - acc2168_shadow_recalc(dev); - break; - } + case 0x01: + dev->regs[dev->reg_idx] = val & 0xd3; + cpu_update_waitstates(); + break; + + case 0x02: + dev->regs[dev->reg_idx] = val & 0x7f; + acc2168_shadow_recalc(dev); + break; + + case 0x03: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x04: + dev->regs[dev->reg_idx] = val; + cpu_cache_ext_enabled = !!(val & 0x01); + cpu_update_waitstates(); + break; + + case 0x05: + dev->regs[dev->reg_idx] = val & 0xf3; + break; + + case 0x06: + case 0x07: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x08: + dev->regs[dev->reg_idx] = val & 0x0f; + break; + + case 0x09: + dev->regs[dev->reg_idx] = val & 0x03; + break; + + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + dev->regs[dev->reg_idx] = val; + break; + + case 0x12: + dev->regs[dev->reg_idx] = val & 0xbb; + break; + + case 0x18: + dev->regs[dev->reg_idx] = val & 0x77; + break; + + case 0x19: + dev->regs[dev->reg_idx] = val & 0xfb; + break; + + case 0x1a: + dev->regs[dev->reg_idx] = val; + cpu_cache_int_enabled = !(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x1b: + dev->regs[dev->reg_idx] = val & 0xef; + break; + } + break; } } - -static uint8_t +static uint8_t acc2168_read(uint16_t addr, void *p) { acc2168_t *dev = (acc2168_t *)p; - if (!(addr & 1)) - return dev->reg_idx; - - return dev->regs[dev->reg_idx]; + return (addr == 0xf3) ? dev->regs[dev->reg_idx] : dev->reg_idx; } static void acc2168_close(void *priv) { - acc2168_t *dev = (acc2168_t *) priv; + acc2168_t *dev = (acc2168_t *)priv; free(dev); } - static void * acc2168_init(const device_t *info) { acc2168_t *dev = (acc2168_t *)malloc(sizeof(acc2168_t)); memset(dev, 0, sizeof(acc2168_t)); - - io_sethandler(0x00f2, 0x0002, - acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev); - device_add(&port_92_inv_device); + device_add(&port_92_device); + io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev); return dev; } - const device_t acc2168_device = { - "ACC 2168", + "ACC 2046/2168", 0, 0, - acc2168_init, acc2168_close, NULL, - { NULL }, NULL, NULL, - NULL -}; + acc2168_init, + acc2168_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; From 2b1e9a5656a607458b21076d4dc72fe9f34da46a Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:11:03 +0200 Subject: [PATCH 50/60] Properly done logging --- src/chipset/acc2168.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 66783022e..b9e6a2c18 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -16,11 +16,13 @@ * Copyright 2019 Sarah Walker. * Copyright 2021 Tiseno100. */ -#include +#include #include +#include #include #include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" #include <86box/timer.h> @@ -36,6 +38,23 @@ #define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) #define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) +#ifdef ENABLE_ACC2168_LOG +int ali1429_do_log = ENABLE_ACC2168_LOG; +static void +acc2168_log(const char *fmt, ...) +{ + va_list ap; + + if (acc2168_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define acc2168_log(fmt, ...) +#endif + typedef struct acc2168_t { uint8_t reg_idx, regs[256]; @@ -59,7 +78,7 @@ acc2168_write(uint16_t addr, uint8_t val, void *p) dev->reg_idx = val; break; case 0xf3: - pclog("dev->regs[%02x] = %02x\n", dev->reg_idx, val); + acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val); switch (dev->reg_idx) { case 0x00: From fea33c18c5bbe57b8239d63b95f2d99c5536b5d0 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:11:46 +0200 Subject: [PATCH 51/60] wrong naming on log. --- src/chipset/acc2168.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index b9e6a2c18..4cdf41a2c 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -39,7 +39,7 @@ #define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) #ifdef ENABLE_ACC2168_LOG -int ali1429_do_log = ENABLE_ACC2168_LOG; +int acc2168_do_log = ENABLE_ACC2168_LOG; static void acc2168_log(const char *fmt, ...) { From 83a8f93d7018ccc59347aceb7cd64f2ae69a06ed Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:23:56 +0200 Subject: [PATCH 52/60] Include a default switch for undocumented registers --- src/acc2168.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/acc2168.c diff --git a/src/acc2168.c b/src/acc2168.c new file mode 100644 index 000000000..384486faa --- /dev/null +++ b/src/acc2168.c @@ -0,0 +1,207 @@ +/* + * 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. + * + * Implementation of the ACC 2046/2168 chipset + * + * + * + * Authors: Sarah Walker, + * Tiseno100 + * + * Copyright 2019 Sarah Walker. + * Copyright 2021 Tiseno100. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + +#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) +#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) +#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16))) +#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) +#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) + +#define ENABLE_ACC2168_LOG 1 + +#ifdef ENABLE_ACC2168_LOG +int acc2168_do_log = ENABLE_ACC2168_LOG; +static void +acc2168_log(const char *fmt, ...) +{ + va_list ap; + + if (acc2168_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define acc2168_log(fmt, ...) +#endif + +typedef struct acc2168_t +{ + uint8_t reg_idx, regs[256]; +} acc2168_t; + +static void +acc2168_shadow_recalc(acc2168_t *dev) +{ + for (uint32_t i = 0; i < 5; i++) + mem_set_mem_state_both(SHADOW_ADDR, SHADOW_SIZE, SHADOW_RECALC); +} + +static void +acc2168_write(uint16_t addr, uint8_t val, void *p) +{ + acc2168_t *dev = (acc2168_t *)p; + + switch (addr) + { + case 0xf2: + dev->reg_idx = val; + break; + case 0xf3: + acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val); + switch (dev->reg_idx) + { + case 0x00: + dev->regs[dev->reg_idx] = val; + break; + + case 0x01: + dev->regs[dev->reg_idx] = val & 0xd3; + cpu_update_waitstates(); + break; + + case 0x02: + dev->regs[dev->reg_idx] = val & 0x7f; + acc2168_shadow_recalc(dev); + break; + + case 0x03: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x04: + dev->regs[dev->reg_idx] = val; + cpu_cache_ext_enabled = !!(val & 0x01); + cpu_update_waitstates(); + break; + + case 0x05: + dev->regs[dev->reg_idx] = val & 0xf3; + break; + + case 0x06: + case 0x07: + dev->regs[dev->reg_idx] = val & 0x1f; + break; + + case 0x08: + dev->regs[dev->reg_idx] = val & 0x0f; + break; + + case 0x09: + dev->regs[dev->reg_idx] = val & 0x03; + break; + + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + dev->regs[dev->reg_idx] = val; + break; + + case 0x12: + dev->regs[dev->reg_idx] = val & 0xbb; + break; + + case 0x18: + dev->regs[dev->reg_idx] = val & 0x77; + break; + + case 0x19: + dev->regs[dev->reg_idx] = val & 0xfb; + break; + + case 0x1a: + dev->regs[dev->reg_idx] = val; + cpu_cache_int_enabled = !(val & 0x40); + cpu_update_waitstates(); + break; + + case 0x1b: + dev->regs[dev->reg_idx] = val & 0xef; + break; + + default: /* ACC 2168 has way more registers which we haven't documented */ + dev->regs[dev->reg_idx] = val; + break; + + } + break; + } +} + +static uint8_t +acc2168_read(uint16_t addr, void *p) +{ + acc2168_t *dev = (acc2168_t *)p; + + return (addr == 0xf3) ? dev->regs[dev->reg_idx] : dev->reg_idx; +} + +static void +acc2168_close(void *priv) +{ + acc2168_t *dev = (acc2168_t *)priv; + + free(dev); +} + +static void * +acc2168_init(const device_t *info) +{ + acc2168_t *dev = (acc2168_t *)malloc(sizeof(acc2168_t)); + memset(dev, 0, sizeof(acc2168_t)); + + device_add(&port_92_device); + io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev); + + return dev; +} + +const device_t acc2168_device = { + "ACC 2046/2168", + 0, + 0, + acc2168_init, + acc2168_close, + NULL, + {NULL}, + NULL, + NULL, + NULL}; From abca8ec142e6b8c69097d8532ac6bc9ee989230b Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:24:15 +0200 Subject: [PATCH 53/60] Delete acc2168.c --- src/acc2168.c | 207 -------------------------------------------------- 1 file changed, 207 deletions(-) delete mode 100644 src/acc2168.c diff --git a/src/acc2168.c b/src/acc2168.c deleted file mode 100644 index 384486faa..000000000 --- a/src/acc2168.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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. - * - * Implementation of the ACC 2046/2168 chipset - * - * - * - * Authors: Sarah Walker, - * Tiseno100 - * - * Copyright 2019 Sarah Walker. - * Copyright 2021 Tiseno100. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/io.h> -#include <86box/mem.h> -#include <86box/port_92.h> -#include <86box/chipset.h> - -#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) -#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY) -#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16))) -#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) -#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) - -#define ENABLE_ACC2168_LOG 1 - -#ifdef ENABLE_ACC2168_LOG -int acc2168_do_log = ENABLE_ACC2168_LOG; -static void -acc2168_log(const char *fmt, ...) -{ - va_list ap; - - if (acc2168_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define acc2168_log(fmt, ...) -#endif - -typedef struct acc2168_t -{ - uint8_t reg_idx, regs[256]; -} acc2168_t; - -static void -acc2168_shadow_recalc(acc2168_t *dev) -{ - for (uint32_t i = 0; i < 5; i++) - mem_set_mem_state_both(SHADOW_ADDR, SHADOW_SIZE, SHADOW_RECALC); -} - -static void -acc2168_write(uint16_t addr, uint8_t val, void *p) -{ - acc2168_t *dev = (acc2168_t *)p; - - switch (addr) - { - case 0xf2: - dev->reg_idx = val; - break; - case 0xf3: - acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val); - switch (dev->reg_idx) - { - case 0x00: - dev->regs[dev->reg_idx] = val; - break; - - case 0x01: - dev->regs[dev->reg_idx] = val & 0xd3; - cpu_update_waitstates(); - break; - - case 0x02: - dev->regs[dev->reg_idx] = val & 0x7f; - acc2168_shadow_recalc(dev); - break; - - case 0x03: - dev->regs[dev->reg_idx] = val & 0x1f; - break; - - case 0x04: - dev->regs[dev->reg_idx] = val; - cpu_cache_ext_enabled = !!(val & 0x01); - cpu_update_waitstates(); - break; - - case 0x05: - dev->regs[dev->reg_idx] = val & 0xf3; - break; - - case 0x06: - case 0x07: - dev->regs[dev->reg_idx] = val & 0x1f; - break; - - case 0x08: - dev->regs[dev->reg_idx] = val & 0x0f; - break; - - case 0x09: - dev->regs[dev->reg_idx] = val & 0x03; - break; - - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - dev->regs[dev->reg_idx] = val; - break; - - case 0x12: - dev->regs[dev->reg_idx] = val & 0xbb; - break; - - case 0x18: - dev->regs[dev->reg_idx] = val & 0x77; - break; - - case 0x19: - dev->regs[dev->reg_idx] = val & 0xfb; - break; - - case 0x1a: - dev->regs[dev->reg_idx] = val; - cpu_cache_int_enabled = !(val & 0x40); - cpu_update_waitstates(); - break; - - case 0x1b: - dev->regs[dev->reg_idx] = val & 0xef; - break; - - default: /* ACC 2168 has way more registers which we haven't documented */ - dev->regs[dev->reg_idx] = val; - break; - - } - break; - } -} - -static uint8_t -acc2168_read(uint16_t addr, void *p) -{ - acc2168_t *dev = (acc2168_t *)p; - - return (addr == 0xf3) ? dev->regs[dev->reg_idx] : dev->reg_idx; -} - -static void -acc2168_close(void *priv) -{ - acc2168_t *dev = (acc2168_t *)priv; - - free(dev); -} - -static void * -acc2168_init(const device_t *info) -{ - acc2168_t *dev = (acc2168_t *)malloc(sizeof(acc2168_t)); - memset(dev, 0, sizeof(acc2168_t)); - - device_add(&port_92_device); - io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev); - - return dev; -} - -const device_t acc2168_device = { - "ACC 2046/2168", - 0, - 0, - acc2168_init, - acc2168_close, - NULL, - {NULL}, - NULL, - NULL, - NULL}; From 92168311bfb6e924bf0db93652767ba3a9533e2b Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:24:32 +0200 Subject: [PATCH 54/60] Position fix. --- src/chipset/acc2168.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 4cdf41a2c..384486faa 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -38,6 +38,8 @@ #define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) #define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) +#define ENABLE_ACC2168_LOG 1 + #ifdef ENABLE_ACC2168_LOG int acc2168_do_log = ENABLE_ACC2168_LOG; static void @@ -154,6 +156,11 @@ acc2168_write(uint16_t addr, uint8_t val, void *p) case 0x1b: dev->regs[dev->reg_idx] = val & 0xef; break; + + default: /* ACC 2168 has way more registers which we haven't documented */ + dev->regs[dev->reg_idx] = val; + break; + } break; } From 84c713411f19a4fc403dbb0b4e9bf860fa9784a4 Mon Sep 17 00:00:00 2001 From: Panagiotis <58827426+tiseno100@users.noreply.github.com> Date: Fri, 1 Jan 2021 20:25:09 +0200 Subject: [PATCH 55/60] Disable logging --- src/chipset/acc2168.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 384486faa..b30a7951e 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -38,8 +38,6 @@ #define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000) #define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW) -#define ENABLE_ACC2168_LOG 1 - #ifdef ENABLE_ACC2168_LOG int acc2168_do_log = ENABLE_ACC2168_LOG; static void From cfb15d3a055227e51cbdf5fdeb74d805eb098129 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 1 Jan 2021 23:22:48 +0100 Subject: [PATCH 56/60] Added some more sanity checks to sdl_blit(). --- src/win/win_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 862927f59..1d9912316 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -234,7 +234,7 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL)) { + if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } From 09c20cb5089b62b209279233ebee66be6c57c92b Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 5 Jan 2021 22:41:40 +0100 Subject: [PATCH 57/60] Fixed the SMC FDC73C665 Super I/O chip. --- src/sio/sio_fdc37c66x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sio/sio_fdc37c66x.c b/src/sio/sio_fdc37c66x.c index 970925e14..6f8797f13 100644 --- a/src/sio/sio_fdc37c66x.c +++ b/src/sio/sio_fdc37c66x.c @@ -282,8 +282,6 @@ fdc37c66x_init(const device_t *info) dev->chip_id = info->local & 0xff; dev->has_ide = !!(info->local & 0x100); - if (dev->has_ide) - io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, dev); From 593b3adcfe8263a7b7fc61acd0c034b594931365 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 6 Jan 2021 06:09:48 +0100 Subject: [PATCH 58/60] Keyboard controller reset is now hard reset, fixes CTRL+ALT+DEL causing the SiS 471 AMI 486 clone to hang in SMM. --- src/device/keyboard_at.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index af2caccbd..74563cf8f 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1059,7 +1059,7 @@ write_output(atkbd_t *dev, uint8_t val) if ((dev->output_port ^ val) & 0x01) { /*Reset*/ if (! (val & 0x01)) { /* Pin 0 selected. */ - softresetx86(); /*Pulse reset!*/ + resetx86(); /*Pulse reset!*/ cpu_set_edx(); } } From 08cc6921732cca24d3a6bb216c092647086c9453 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 6 Jan 2021 06:32:19 +0100 Subject: [PATCH 59/60] LPT ports now no longer use the LPT device functions if priv is NULL. --- src/lpt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lpt.c b/src/lpt.c index bf0cc339e..6332417d3 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -108,7 +108,7 @@ lpt_write(uint16_t port, uint8_t val, void *priv) switch (port & 3) { case 0: - if (dev->dt && dev->dt->write_data) + if (dev->dt && dev->dt->write_data && dev->priv) dev->dt->write_data(val, dev->priv); dev->dat = val; break; @@ -117,7 +117,7 @@ lpt_write(uint16_t port, uint8_t val, void *priv) break; case 2: - if (dev->dt && dev->dt->write_ctrl) + if (dev->dt && dev->dt->write_ctrl && dev->priv) dev->dt->write_ctrl(val, dev->priv); dev->ctrl = val; dev->enable_irq = val & 0x10; @@ -134,21 +134,21 @@ lpt_read(uint16_t port, void *priv) switch (port & 3) { case 0: - if (dev->dt && dev->dt->read_data) + if (dev->dt && dev->dt->read_data && dev->priv) ret = dev->dt->read_data(dev->priv); else ret = dev->dat; break; case 1: - if (dev->dt && dev->dt->read_status) + if (dev->dt && dev->dt->read_status && dev->priv) ret = dev->dt->read_status(dev->priv) | 0x07; else ret = 0xdf; break; case 2: - if (dev->dt && dev->dt->read_ctrl) + if (dev->dt && dev->dt->read_ctrl && dev->priv) ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; else ret = 0xe0 | dev->ctrl | dev->enable_irq; From afb896f1eb6ec052d865f388db77656adb529260 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 6 Jan 2021 06:36:39 +0100 Subject: [PATCH 60/60] Port 92h now hard resets as well. --- src/port_92.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/port_92.c b/src/port_92.c index 83efb3213..d46d2327b 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -71,7 +71,7 @@ port_92_readw(uint16_t port, void *priv) static void port_92_pulse(void *priv) { - softresetx86(); + resetx86(); cpu_set_edx(); }