diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 36b9010e3..619d2c871 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -57,6 +57,7 @@ jobs: ${{ matrix.environment.prefix }}-zlib ${{ matrix.environment.prefix }}-libpng ${{ matrix.environment.prefix }}-libvncserver + ${{ matrix.environment.prefix }}-winpthreads - uses: actions/checkout@v2 - name: make run: make -fwin/makefile.mingw -j DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} X64=${{ matrix.environment.x64 }} CLANG=${{ matrix.clang }} VNC=n diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 294442bf4..9973969e4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -62,13 +62,16 @@ jobs: msystem: ${{ matrix.environment.msystem }} install: >- ${{ matrix.environment.prefix }}-ninja - ${{ matrix.environment.prefix }}-toolchain + ${{ matrix.environment.prefix }}-gcc + ${{ matrix.environment.prefix }}-clang + ${{ matrix.environment.prefix }}-pkg-config ${{ matrix.environment.prefix }}-openal ${{ matrix.environment.prefix }}-freetype ${{ matrix.environment.prefix }}-SDL2 ${{ matrix.environment.prefix }}-zlib ${{ matrix.environment.prefix }}-libpng ${{ matrix.environment.prefix }}-libvncserver + ${{ matrix.environment.prefix }}-winpthreads - uses: actions/checkout@v2 - name: Configure CMake run: >- @@ -128,3 +131,68 @@ jobs: with: name: '86Box-${{ matrix.build.name }}-VS2019-${{ matrix.target-arch }}-${{ matrix.toolset }}-${{ github.sha }}' path: build/artifacts/bin/** + + linux: + name: "Linux GCC 11" + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build: + - name: Debug + dev-build: off + new-dynarec: off + type: Debug + - name: Dev + dev-build: on + new-dynarec: on + type: Debug + + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev + - name: Configure CMake + run: >- + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + -D CMAKE_C_COMPILER=gcc-11 -D CMAKE_CXX_COMPILER=g++-11 + - name: Build + run: cmake --build build --target install + + macos: + name: "macOS 11" + + runs-on: macos-11 + strategy: + fail-fast: false + matrix: + build: + - name: Debug + dev-build: off + new-dynarec: off + type: Debug + - name: Dev + dev-build: on + new-dynarec: on + type: Debug + + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: brew install freetype sdl2 libpng openal-soft + - name: Configure CMake + run: >- + cmake -S . -B build + -D CMAKE_INSTALL_PREFIX=./build/artifacts + -D DEV_BRANCH=${{ matrix.build.dev-build }} + -D NEW_DYNAREC=${{ matrix.build.new-dynarec }} + -D VNC=OFF + -D CMAKE_BUILD_TYPE=${{ matrix.build.type }} + - name: Build + run: cmake --build build --target install diff --git a/CMakeLists.txt b/CMakeLists.txt index 68b9e760e..59a3b34f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,10 @@ CMAKE_DEPENDENT_OPTION(VNC "VNC renderer" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) CMAKE_DEPENDENT_OPTION(VECT486VL "HP Vectra 486VL" ON "DEV_BRANCH" OFF) +if(WIN32) + option(PTHREAD "Use POSIX threads (pthreads) instead of Win32 threads" ON) +endif() + # HACK: Avoid a MSVC2019 compiler bug on ARM64 Debug builds if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64") # Define a cache option in case somebody wants to disable this workaround @@ -100,4 +104,11 @@ if(MSVC_TOOLSET_VERSION GREATER_EQUAL 142 AND ARCH STREQUAL "arm64") endif() endif() +# HACK: MinGW and macOS <10.15 does not have `timespec_get` +include(CheckSymbolExists) +check_symbol_exists(timespec_get time.h HAS_TIMESPEC_GET) +if(HAS_TIMESPEC_GET) + add_compile_definitions(HAS_TIMESPEC_GET) +endif() + add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f997ae439..08b441d3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,22 @@ if(VNC) target_link_libraries(86Box vnc vncserver ws2_32) endif() +if(NOT WIN32 OR PTHREAD) + target_sources(86Box PRIVATE thread.c) + if(WIN32 AND VCPKG_TOOLCHAIN) + find_package(pthreads REQUIRED) + if (PThreads4W_FOUND) + target_link_libraries(86Box PThreads4W::PThreads4W) + else() + target_link_libraries(86Box pthreads) + endif() + else() + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + target_link_libraries(86Box Threads::Threads) + endif() +endif() + target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd net print scsi sio snd vid voodoo plat ui) @@ -71,8 +87,10 @@ find_package(SDL2 REQUIRED) include_directories(${SDL2_INCLUDE_DIRS}) if(MINGW) target_link_libraries(86Box SDL2::SDL2-static) -else() +elseif(WIN32) target_link_libraries(86Box SDL2::SDL2) +else() + target_link_libraries(86Box ${SDL2_LIBRARIES}) endif() find_package(PNG REQUIRED) diff --git a/src/chipset/82c100.c b/src/chipset/82c100.c new file mode 100644 index 000000000..c7e84c612 --- /dev/null +++ b/src/chipset/82c100.c @@ -0,0 +1,406 @@ +/* + * 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 Chips&Technology's 82C100 chipset. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2021 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include "cpu.h" +#include "x86.h" +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/nmi.h> +#include <86box/port_92.h> +#include <86box/rom.h> +#include <86box/chipset.h> + + +typedef struct +{ + int enabled; + uint32_t virt, phys; +} ems_page_t; + + +typedef struct +{ + uint8_t index, access; + uint16_t ems_io_base; + uint32_t ems_window_base; + uint8_t ems_page_regs[4], + regs[256]; + ems_page_t ems_pages[4]; + mem_mapping_t ems_mappings[4]; +} ct_82c100_t; + + +#ifdef ENABLE_CT_82C100_LOG +int ct_82c100_do_log = ENABLE_CT82C100_LOG; + + +static void +ct_82c100_log(const char *fmt, ...) +{ + va_list ap; + + if (ct_82c100_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define ct_82c100_log(fmt, ...) +#endif + + +static void +ct_82c100_ems_pages_recalc(ct_82c100_t *dev) +{ + int i; + uint32_t page_base; + + for (i = 0; i < 4; i++) { + page_base = dev->ems_window_base + (i << 14); + if ((i == 1) || (i == 2)) + page_base ^= 0xc000; + if (dev->ems_page_regs[i] & 0x80) { + dev->ems_pages[i].virt = page_base; + dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14); + ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i, + dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff, + dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff); + mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000); + mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } else { + ct_82c100_log("Disabling EMS page %i\n", i); + mem_mapping_disable(&(dev->ems_mappings[i])); + mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + } + } + + flushmmucache_nopc(); +} + + +static void +ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + ct_82c100_log("[%04X] dev->ems_page_regs[%i] = %02X\n", port, port >> 14, val); + dev->ems_page_regs[port >> 14] = val; + ct_82c100_ems_pages_recalc(dev); +} + + +static uint8_t +ct_82c100_ems_in(uint16_t port, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + uint8_t ret = 0xff; + + ret = dev->ems_page_regs[port >> 14]; + + return ret; +} + + +static void +ct_82c100_ems_update(ct_82c100_t *dev) +{ + int i; + + for (i = 0; i < 4; i++) { + ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); + io_handler(0, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + } + + dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0); + + for (i = 0; i < 4; i++) { + ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14)); + io_handler(1, dev->ems_io_base + (i << 14), 1, + ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev); + } + + dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14); + + ct_82c100_ems_pages_recalc(dev); +} + + +static void +ct_82c100_reset(void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + ct_82c100_log("Reset\n"); + + memset(dev->regs, 0x00, sizeof(dev->regs)); + memset(dev->ems_page_regs, 0x00, sizeof(dev->ems_page_regs)); + + dev->index = dev->access = 0x00; + + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */ + dev->regs[0x43] = 0x30; + dev->regs[0x48] = 0x01; + + use_custom_nmi_vector = 0; + ct_82c100_ems_update(dev); + + /* ADDITIONAL I/O REGISTERS */ +} + + +static void +ct_82c100_out(uint16_t port, uint8_t val, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + if (port == 0x0022) { + dev->index = val; + dev->access = 1; + } else if (port == 0x0023) { + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40: + dev->regs[0x40] = val & 0xc7; + /* TODO: Clock stuff - needs CPU speed change functionality that's + going to be implemented in 86box v4.0. + Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */ + break; + case 0x41: + dev->regs[0x41] = val & 0xed; + /* TODO: Where is the Software Reset Function that's enabled by + setting bit 6 to 1? */ + break; + case 0x42: + dev->regs[0x42] = val & 0x01; + break; + case 0x43: + dev->regs[0x43] = val; + break; + case 0x44: + dev->regs[0x44] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val); + break; + case 0x45: + dev->regs[0x45] = val; + custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8); + break; + case 0x46: + dev->regs[0x46] = val; + custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16); + break; + case 0x47: + dev->regs[0x47] = val; + custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24); + break; + case 0x48: case 0x49: + dev->regs[dev->index] = val; + break; + case 0x4b: + dev->regs[0x4b] = val; + use_custom_nmi_vector = !!(val & 0x40); + break; + case 0x4c: + ct_82c100_log("CS4C: %02X\n", val); + dev->regs[0x4c] = val; + ct_82c100_ems_update(dev); + break; + } + dev->access = 0; + } + } else if (port == 0x72) + dev->regs[0x72] = val & 0x7e; + else if (port == 0x7e) + dev->regs[0x7e] = val; + else if (port == 0x7f) { + /* Bit 3 is Software Controlled Reset, asserted if set. Will be + done in the feature/machine_and_kb branch using hardresetx86(). */ + dev->regs[0x7f] = val; + if ((dev->regs[0x41] & 0x40) && (val & 0x08)) { + softresetx86(); + cpu_set_edx(); + ct_82c100_reset(dev); + } + } +} + + +static uint8_t +ct_82c100_in(uint16_t port, void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + uint8_t ret = 0xff; + + if (port == 0x0022) + ret = dev->index; + else if (port == 0x0023) { + if (dev->access) { + switch (dev->index) { + /* INTERNAL CONFIGURATION/CONTROL REGISTERS */ + case 0x40 ... 0x49: + case 0x4b: case 0x4c: + ret = dev->regs[dev->index]; + break; + } + dev->access = 0; + } + } else if (port == 0x72) + ret = dev->regs[0x72]; + else if (port == 0x7e) + ret = dev->regs[0x7e]; + else if (port == 0x7f) + ret = dev->regs[0x7f]; + + return ret; +} + + +static uint8_t +mem_read_emsb(uint32_t addr, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + uint8_t ret = 0xff; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + ret = ram[addr]; + + ct_82c100_log("mem_read_emsb(%08X = %08X): %02X\n", old_addr, addr, ret); + + return ret; +} + + +static uint16_t +mem_read_emsw(uint32_t addr, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; + uint16_t ret = 0xffff; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + ret = *(uint16_t *)&ram[addr]; + + ct_82c100_log("mem_read_emsw(%08X = %08X): %04X\n", old_addr, addr, ret); + + return ret; +} + + +static void +mem_write_emsb(uint32_t addr, uint8_t val, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + ram[addr] = val; + + ct_82c100_log("mem_write_emsb(%08X = %08X, %02X)\n", old_addr, addr, val); +} + + +static void +mem_write_emsw(uint32_t addr, uint16_t val, void *priv) +{ + ems_page_t *page = (ems_page_t *)priv; +#ifdef ENABLE_CT_82C100_LOG + uint32_t old_addr = addr; +#endif + + addr = addr - page->virt + page->phys; + + if (addr < ((uint32_t)mem_size << 10)) + *(uint16_t *)&ram[addr] = val; + + ct_82c100_log("mem_write_emsw(%08X = %08X, %04X)\n", old_addr, addr, val); +} + + +static void +ct_82c100_close(void *priv) +{ + ct_82c100_t *dev = (ct_82c100_t *) priv; + + free(dev); +} + + +static void * +ct_82c100_init(const device_t *info) +{ + ct_82c100_t *dev; + uint32_t i; + + dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t)); + memset(dev, 0x00, sizeof(ct_82c100_t)); + + ct_82c100_reset(dev); + + io_sethandler(0x0022, 2, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + io_sethandler(0x0072, 1, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + io_sethandler(0x007e, 2, + ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev); + + for (i = 0; i < 4; i++) { + mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000, + mem_read_emsb, mem_read_emsw, NULL, + mem_write_emsb, mem_write_emsw, NULL, + ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]); + mem_mapping_disable(&(dev->ems_mappings[i])); + } + + mem_mapping_disable(&ram_mid_mapping); + + device_add(&port_92_device); + + return(dev); +} + + +const device_t ct_82c100_device = { + "C&T 82C100", + 0, + 0, + ct_82c100_init, ct_82c100_close, ct_82c100_reset, + { NULL }, NULL, NULL, + NULL +}; diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 76cf45db0..12006a878 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -13,7 +13,7 @@ # Copyright 2020,2021 David Hrdlička. # -add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c +add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5598.c diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index a68dee7ae..9f3f844a4 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4314,6 +4314,56 @@ static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) *host_reg1 = REG_EBX; } +static inline int64_t x87_fround16_64(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t)((int16_t)floor(b)); + case 2: /*Up*/ + return (int64_t)((int16_t)ceil(b)); + case 3: /*Chop*/ + return (int64_t)((int16_t)b); + } + + return 0; +} +static inline int64_t x87_fround32_64(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return (int64_t) a; + else if ((b - a) > (c - b)) + return (int64_t) c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int64_t)((int32_t)floor(b)); + case 2: /*Up*/ + return (int64_t)((int32_t)ceil(b)); + case 3: /*Chop*/ + return (int64_t)((int32_t)b); + } + + return 0; +} static inline int64_t x87_fround(double b) { int64_t a, c; @@ -4363,7 +4413,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround16_64); addbyte(0x93); /*XCHG EBX, EAX*/ @@ -4393,7 +4443,7 @@ static inline int FP_LOAD_REG_INT(int reg) addbyte(0xc5); addbyte((uint8_t)cpu_state_offset(ST)); - CALL_FUNC((uintptr_t)x87_fround); + CALL_FUNC((uintptr_t)x87_fround32_64); addbyte(0x93); /*XCHG EBX, EAX*/ diff --git a/src/config.c b/src/config.c index c10c3049d..6d26fe9c6 100644 --- a/src/config.c +++ b/src/config.c @@ -505,7 +505,7 @@ load_general(void) video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 1); + video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); video_filter_method = config_get_int(cat, "video_filter_method", 1); @@ -524,7 +524,10 @@ load_general(void) update_icons = config_get_int(cat, "update_icons", 1); window_remember = config_get_int(cat, "window_remember", 0); - if (window_remember) { + if (window_remember || (vid_resize & 2)) { + if (!window_remember) + config_delete_var(cat, "window_remember"); + p = config_get_string(cat, "window_coordinates", NULL); if (p == NULL) p = "0, 0, 0, 0"; @@ -2156,8 +2159,11 @@ save_general(void) else config_set_int(cat, "update_icons", update_icons); - if (window_remember) { - config_set_int(cat, "window_remember", window_remember); + if (window_remember || (vid_resize & 2)) { + if (window_remember) + config_set_int(cat, "window_remember", window_remember); + else + config_delete_var(cat, "window_remember"); sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); config_set_string(cat, "window_coordinates", temp); diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 3fbcfb0ed..900286580 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -38,6 +38,10 @@ /* Is the CPU 8088 or 8086. */ int is8086 = 0; +uint8_t use_custom_nmi_vector = 0; +uint32_t custom_nmi_vector = 0x00000000; + + /* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ static uint8_t pfq[6]; @@ -578,6 +582,9 @@ reset_808x(int hard) prefetching = 1; cpu_alu_op = 0; + + use_custom_nmi_vector = 0x00; + custom_nmi_vector = 0x00000000; } @@ -943,6 +950,41 @@ interrupt(uint16_t addr) } +static void +custom_nmi(void) +{ + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; + + cpu_state.eaaddr = 0x0002; + old_cs = CS; + access(5, 16); + (void) readmemw(0, cpu_state.eaaddr); + new_ip = custom_nmi_vector & 0xffff; + wait(1, 0); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); + (void) readmemw(0, cpu_state.eaaddr); + new_cs = custom_nmi_vector >> 16; + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & 0x0fd7; + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); +} + + static int irq_pending(void) { @@ -967,7 +1009,10 @@ check_interrupts(void) } if (nmi && nmi_enable && nmi_mask) { nmi_enable = 0; - interrupt(2); + if (use_custom_nmi_vector) + custom_nmi(); + else + interrupt(2); #ifndef OLD_NMI_BEHAVIOR nmi = 0; #endif diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 83664828c..b28934951 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -715,6 +715,9 @@ extern int reset_on_hlt, hlt_reset_pending; extern cyrix_t cyrix; +extern uint8_t use_custom_nmi_vector; +extern uint32_t custom_nmi_vector; + extern void (*cpu_exec)(int cycs); extern uint8_t do_translate, do_translate2; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index e40d64400..b29e20ce0 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -15,12 +15,14 @@ * Miran Grca, * Fred N. van Kempen, * RichardG, + * dob205, * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 leilei. * Copyright 2016-2019 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2020 RichardG. + * Copyright 2021 dob205. */ #include #include @@ -760,6 +762,9 @@ const cpu_family_t cpu_families[] = { .name = "K6 (Model 6)", .internal_name = "k6_m6", .cpus = (const CPU[]) { + {"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ + {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ + {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, {"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, @@ -1513,6 +1518,9 @@ static const cpu_legacy_table_t cpus_K5[] = { }; static const cpu_legacy_table_t cpus_K56[] = { + {"k6_m6", 66666666, 1.0}, + {"k6_m6", 100000000, 1.5}, + {"k6_m6", 133333333, 2.0}, {"k6_m6", 166666666, 2.5}, {"k6_m6", 200000000, 3.0}, {"k6_m6", 233333333, 3.5}, diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 17861fa57..9e06a343e 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -152,10 +152,72 @@ static __inline double x87_pop() return t; } +static __inline int16_t x87_fround16(double b) +{ + int16_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int16_t)floor(b); + c = (int16_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int16_t)floor(b); + case 2: /*Up*/ + return (int16_t)ceil(b); + case 3: /*Chop*/ + return (int16_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround16_64(double b) +{ + return (int64_t) x87_fround16(b); +} + +static __inline int32_t x87_fround32(double b) +{ + int32_t a, c; + + switch ((cpu_state.npxc >> 10) & 3) + { + case 0: /*Nearest*/ + a = (int32_t)floor(b); + c = (int32_t)floor(b + 1.0); + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; + case 1: /*Down*/ + return (int32_t)floor(b); + case 2: /*Up*/ + return (int32_t)ceil(b); + case 3: /*Chop*/ + return (int32_t)b; + } + + return 0; +} + +static __inline int64_t x87_fround32_64(double b) +{ + return (int64_t) x87_fround32(b); +} + static __inline int64_t x87_fround(double b) { int64_t a, c; - + switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index f742196ea..5e754fc90 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -42,24 +42,20 @@ static int opFILDiw_a32(uint32_t fetchdat) static int opFISTiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); + seteaw(x87_fround16(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return cpu_state.abrt; } @@ -67,12 +63,10 @@ static int opFISTiw_a32(uint32_t fetchdat) static int opFISTPiw_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -80,12 +74,10 @@ static int opFISTPiw_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPiw_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; + seteaw(x87_fround16(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_16) : (x87_timings.fist_16 * cpu_multi)); return 0; @@ -240,24 +232,20 @@ static int opFILDil_a32(uint32_t fetchdat) static int opFISTil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } #ifndef FPU_8087 static int opFISTil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); + seteal(x87_fround32(ST(0))); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return cpu_state.abrt; } @@ -265,12 +253,10 @@ static int opFISTil_a32(uint32_t fetchdat) static int opFISTPil_a16(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; @@ -278,12 +264,10 @@ static int opFISTPil_a16(uint32_t fetchdat) #ifndef FPU_8087 static int opFISTPil_a32(uint32_t fetchdat) { - int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); - temp64 = x87_fround(ST(0)); - seteal((int32_t)temp64); if (cpu_state.abrt) return 1; + seteal(x87_fround32(ST(0))); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fist_32) : (x87_timings.fist_32 * cpu_multi)); return 0; diff --git a/src/device/serial.c b/src/device/serial.c index 25c9c0a49..3de0c6826 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -128,7 +128,7 @@ serial_update_ints(serial_t *dev) dev->iir = 0; } - if (stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { + if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { if (dev->type >= SERIAL_NS16450) picintlevel(1 << dev->irq); else @@ -615,7 +615,7 @@ serial_remove(serial_t *dev) void -serial_setup(serial_t *dev, uint16_t addr, int irq) +serial_setup(serial_t *dev, uint16_t addr, uint8_t irq) { serial_log("Adding serial port %i at %04X...\n", dev->inst, addr); diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 4da50795e..545eafd72 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1892,9 +1892,10 @@ fdc_is_verify(fdc_t *fdc) int -fdc_data(fdc_t *fdc, uint8_t data) +fdc_data(fdc_t *fdc, uint8_t data, int last) { - int result = 0; + int i, result = 0; + int n; if (fdc->deleted & 2) { /* We're in a VERIFY command, so return with 0. */ @@ -1924,27 +1925,41 @@ fdc_data(fdc_t *fdc, uint8_t data) } } } else { - result = dma_channel_write(fdc->dma_ch, data); - if (fdc->tc) return -1; - if (result & DMA_OVER) { - fdc->data_ready = 1; - fdc->stat = 0xd0; - fdc->tc = 1; - return -1; - } - if (!fdc->fifo || (fdc->tfifo < 1)) { fdc->data_ready = 1; fdc->stat = 0xd0; + + fdc->fifobufpos = 0; + + result = dma_channel_write(fdc->dma_ch, data); + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } } else { - fdc_fifo_buf_advance(fdc); - if (fdc->fifobufpos == 0) { + /* FIFO enabled */ + fdc_fifo_buf_write(fdc, data); + if (last || (fdc->fifobufpos == 0)) { /* We have wrapped around, means FIFO is over */ fdc->data_ready = 1; fdc->stat = 0xd0; + + n = (fdc->fifobufpos > 0) ? (fdc->fifobufpos - 1) : fdc->tfifo; + if (fdc->fifobufpos > 0) + fdc->fifobufpos = 0; + + for (i = 0; i <= n; i++) { + result = dma_channel_write(fdc->dma_ch, fdc->fifobuf[i]); + + if (result & DMA_OVER) { + fdc->tc = 1; + return -1; + } + } } } } @@ -2057,10 +2072,10 @@ fdc_writeprotect(fdc_t *fdc) int fdc_getdata(fdc_t *fdc, int last) { - int data; + int i, data = 0; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo || (fdc->tfifo < 1)) { data = fdc->dat; if (!last) @@ -2072,20 +2087,32 @@ int fdc_getdata(fdc_t *fdc, int last) fdc->stat = 0xb0; } } else { - data = dma_channel_read(fdc->dma_ch); + if (!fdc->fifo || (fdc->tfifo < 1)) { + data = dma_channel_read(fdc->dma_ch); + + if (data & DMA_OVER) + fdc->tc = 1; - if (!fdc->fifo) { if (!last) fdc->stat = 0x90; } else { - fdc_fifo_buf_advance(fdc); + if (fdc->fifobufpos == 0) { + for (i = 0; i <= fdc->tfifo; i++) { + data = dma_channel_read(fdc->dma_ch); + fdc->fifobuf[i] = data; + + if (data & DMA_OVER) { + fdc->tc = 1; + break; + } + } + } + + data = fdc_fifo_buf_read(fdc); if (!last && (fdc->fifobufpos == 0)) fdc->stat = 0x90; } - - if (data & DMA_OVER) - fdc->tc = 1; } return data & 0xff; diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index f0326d3d3..ac4de1ee4 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -235,7 +235,6 @@ static d86f_t *d86f[FDD_NUM]; static uint16_t CRCTable[256]; static fdc_t *d86f_fdc; uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ -uint64_t table[256]; uint16_t d86f_side_flags(int drive); @@ -1499,10 +1498,15 @@ uint8_t d86f_get_data(int drive, int base) { d86f_t *dev = d86f[drive]; - int data; + int data, byte_count; - if (dev->data_find.bytes_obtained < (d86f_get_data_len(drive) + base)) { - data = fdc_getdata(d86f_fdc, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) + base - 1)); + if (fdd_get_turbo(drive) && (dev->version == 0x0063)) + byte_count = dev->turbo_pos; + else + byte_count = dev->data_find.bytes_obtained; + + if (byte_count < (d86f_get_data_len(drive) + base)) { + data = fdc_getdata(d86f_fdc, byte_count == (d86f_get_data_len(drive) + base - 1)); if ((data & DMA_OVER) || (data == -1)) { dev->dma_over++; if (data == -1) @@ -1578,7 +1582,7 @@ d86f_read_sector_data(int drive, int side) } else { if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, data); + read_status = fdc_data(d86f_fdc, data, dev->data_find.bytes_obtained == (d86f_get_data_len(drive) - 1)); if (read_status == -1) dev->dma_over++; } @@ -2131,23 +2135,24 @@ d86f_turbo_read(int drive, int side) dat = d86f_handler[drive].read_data(drive, side, dev->turbo_pos); else dat = (random_generate() & 0xff); - dev->turbo_pos++; if (dev->state == STATE_11_SCAN_DATA) { /* Scan/compare command. */ recv_data = d86f_get_data(drive, 0); d86f_compare_byte(drive, recv_data, dat); } else { - if (dev->data_find.bytes_obtained < (128UL << dev->last_sector.id.n)) { + if (dev->turbo_pos < (128UL << dev->req_sector.id.n)) { if (dev->state != STATE_16_VERIFY_DATA) { - read_status = fdc_data(d86f_fdc, dat); + read_status = fdc_data(d86f_fdc, dat, dev->turbo_pos == ((128UL << dev->req_sector.id.n) - 1)); if (read_status == -1) dev->dma_over++; } } } - if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { + dev->turbo_pos++; + + if (dev->turbo_pos >= (128UL << dev->req_sector.id.n)) { dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; if ((flags & SECTOR_CRC_ERROR) && (dev->state != STATE_02_READ_DATA)) { #ifdef ENABLE_D86F_LOG diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index 6e9b04d24..0c0e36299 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -37,6 +37,7 @@ extern const device_t ali6117d_device; extern const device_t amd640_device; /* C&T */ +extern const device_t ct_82c100_device; extern const device_t neat_device; extern const device_t scat_device; extern const device_t scat_4_device; @@ -65,6 +66,7 @@ extern const device_t i420zx_device; extern const device_t i430lx_device; extern const device_t i430nx_device; extern const device_t i430fx_device; +extern const device_t i430fx_old_device; extern const device_t i430fx_rev02_device; extern const device_t i430hx_device; extern const device_t i430vx_device; @@ -84,6 +86,7 @@ extern const device_t sio_device; extern const device_t sio_zb_device; extern const device_t piix_device; +extern const device_t piix_old_device; extern const device_t piix_rev02_device; extern const device_t piix3_device; extern const device_t piix4_device; diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 5e2d50d06..87404e174 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -157,7 +157,7 @@ extern void fdc_set_base(fdc_t *fdc, int base); extern void fdc_set_irq(fdc_t *fdc, int irq); extern void fdc_set_dma_ch(fdc_t *fdc, int dma_ch); extern int fdc_getdata(fdc_t *fdc, int last); -extern int fdc_data(fdc_t *fdc, uint8_t data); +extern int fdc_data(fdc_t *fdc, uint8_t data, int last); extern void fdc_sectorid(fdc_t *fdc, uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fd01e37eb..69ba7645e 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -622,6 +622,9 @@ extern int machine_tandy_init(const machine_t *); extern int machine_tandy1000hx_init(const machine_t *); extern int machine_tandy1000sl2_init(const machine_t *); +/* m_v86p.c */ +extern int machine_v86p_init(const machine_t *); + #ifdef EMU_DEVICE_H extern const device_t *tandy1k_get_device(void); extern const device_t *tandy1k_hx_get_device(void); @@ -648,6 +651,7 @@ extern int machine_xt_pc4i_init(const machine_t *); extern int machine_xt_mpc1600_init(const machine_t *); extern int machine_xt_pcspirit_init(const machine_t *); extern int machine_xt_pc700_init(const machine_t *); +extern int machine_xt_multitechpc500_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); diff --git a/src/include/86box/nvr.h b/src/include/86box/nvr.h index ceb1bc459..f1776bf79 100644 --- a/src/include/86box/nvr.h +++ b/src/include/86box/nvr.h @@ -121,6 +121,7 @@ extern void nvr_wp_set(int set, int h, nvr_t *nvr); extern void nvr_via_wp_set(int set, int reg, nvr_t *nvr); extern void nvr_bank_set(int base, uint8_t bank, nvr_t *nvr); extern void nvr_lock_set(int base, int size, int lock, nvr_t *nvr); +extern void nvr_irq_set(int irq, nvr_t *nvr); #endif /*EMU_NVR_H*/ diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 605482638..95a74f65f 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -36,7 +36,7 @@ extern int stricmp(const char* s1, const char* s2); extern int strnicmp(const char* s1, const char* s2, size_t n); #endif -#if defined(UNIX) && defined(FREEBSD) || defined(__APPLE__) +#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__) /* FreeBSD has largefile by default. */ # define fopen64 fopen # define fseeko64 fseeko diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index 59e179903..0b6b99aa5 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -77,7 +77,7 @@ extern serial_t * serial_attach(int port, void *priv); extern void serial_remove(serial_t *dev); extern void serial_set_type(serial_t *dev, int type); -extern void serial_setup(serial_t *dev, uint16_t addr, int irq); +extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq); extern void serial_clear_fifo(serial_t *dev); extern void serial_write_fifo(serial_t *dev, uint8_t dat); extern void serial_set_next_inst(int ni); diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index bf9f5526c..f409f4d48 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -20,6 +20,7 @@ extern void vt82c686_sio_write(uint8_t addr, uint8_t val, void *priv); extern const device_t acc3221_device; extern const device_t f82c710_device; +extern const device_t f82c606_device; extern const device_t fdc37c651_device; extern const device_t fdc37c661_device; extern const device_t fdc37c663_device; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index eed2d2ad2..91559aa72 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -153,6 +153,7 @@ typedef struct svga_t /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ int force_dword_mode; + int force_byte_mode; int remap_required; uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); @@ -201,7 +202,7 @@ void svga_close(svga_t *svga); uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +void svga_doblit(int wx, int wy, svga_t *svga); enum { diff --git a/src/include/86box/vid_svga_render_remap.h b/src/include/86box/vid_svga_render_remap.h index c2e48f1b2..5b7f0fe18 100644 --- a/src/include/86box/vid_svga_render_remap.h +++ b/src/include/86box/vid_svga_render_remap.h @@ -101,7 +101,7 @@ void svga_recalc_remap_func(svga_t *svga) { int func_nr; - if (svga->fb_only) + if (svga->fb_only || svga->force_byte_mode) func_nr = 0; else { if (svga->force_dword_mode) diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 59fead3b9..7aac2b633 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -84,7 +84,7 @@ typedef rgb_t PALETTE[256]; extern int changeframecount; extern volatile int screenshots; -extern bitmap_t *buffer32, *render_buffer; +extern bitmap_t *buffer32; extern PALETTE cgapal, cgapal_mono[6]; extern uint32_t pal_lookup[256]; @@ -150,10 +150,10 @@ extern void video_inform(int type, const video_timings_t *ptr); extern int video_get_type(void); -extern void video_setblit(void(*blit)(int,int,int,int,int,int)); +extern void video_setblit(void(*blit)(int,int,int,int)); extern void video_blend(int x, int y); -extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_memtoscreen_8(int x, int y, int w, int h); +extern void video_blit_memtoscreen(int x, int y, int w, int h); extern void video_blit_complete(void); extern void video_wait_for_blit(void); extern void video_wait_for_buffer(void); @@ -249,6 +249,9 @@ extern const device_t compaq_cga_2_device; extern const device_t ogc_device; extern const device_t ogc_m24_device; +/* Chips & Technologies 82C425 */ +extern const device_t f82c425_video_device; + /* NCR NGA */ extern const device_t nga_device; @@ -327,6 +330,7 @@ extern const device_t s3_metheus_86c928_isa_device; extern const device_t s3_metheus_86c928_vlb_device; extern const device_t s3_spea_mirage_86c801_isa_device; extern const device_t s3_spea_mirage_86c805_vlb_device; +extern const device_t s3_mirocrystal_8s_805_vlb_device; extern const device_t s3_mirocrystal_10sd_805_vlb_device; extern const device_t s3_phoenix_86c801_isa_device; extern const device_t s3_phoenix_86c805_vlb_device; @@ -346,6 +350,7 @@ extern const device_t s3_phoenix_trio64vplus_pci_device; extern const device_t s3_phoenix_trio64vplus_onboard_pci_device; extern const device_t s3_mirocrystal_20sv_964_vlb_device; extern const device_t s3_mirocrystal_20sv_964_pci_device; +extern const device_t s3_mirocrystal_20sd_864_vlb_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; @@ -354,8 +359,9 @@ 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_mirovideo_40sv_968_pci_device; -extern const device_t s3_mirovideo_40sv_968_vlb_device; +extern const device_t s3_mirovideo_40sv_ergo_968_pci_device; +extern const device_t s3_phoenix_vision968_pci_device; +extern const device_t s3_phoenix_vision968_vlb_device; extern const device_t s3_spea_mercury_p64v_pci_device; extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; extern const device_t s3_elsa_winner2000_pro_x_pci_device; diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 9b16413f6..ac62fbe16 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -16,7 +16,8 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c m_xt_philips.c m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c - m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_at.c m_at_commodore.c + m_amstrad.c m_europc.c m_xt_olivetti.c m_tandy.c m_v86p.c + m_at.c m_at_commodore.c m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 24fc1be51..10e4df12e 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -577,10 +577,10 @@ vid_poll_1512(void *priv) } if (enable_overscan) { - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); } else { - video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen_8(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); } } @@ -1403,7 +1403,7 @@ lcdm_poll(amsvid_t *vid) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, mda->firstline, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, mda->firstline, xsize, ysize); frames++; video_res_x = mda->crtc[1]; video_res_y = mda->crtc[6]; @@ -1571,7 +1571,7 @@ lcdc_poll(amsvid_t *vid) video_force_resize_set(0); } - video_blit_memtoscreen(0, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen(0, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); } diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index e0aef82ef..4772c3ccc 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -514,7 +514,7 @@ compaq_plasma_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x400 resolution */ diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index cf012a27b..b52c8ef03 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -590,7 +590,7 @@ void t3100e_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x400 resolution */ diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index c51dbf03a..c54c7f0c7 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -566,17 +566,17 @@ vid_poll(void *p) if (enable_overscan) { if (pcjr->composite) - video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1, + video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, 0, ((pcjr->lastline - pcjr->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (pcjr->firstline - 4) << 1, xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); } else { if (pcjr->composite) - video_blit_memtoscreen(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1, + video_blit_memtoscreen(8, pcjr->firstline << 1, xsize, (pcjr->lastline - pcjr->firstline) << 1); else - video_blit_memtoscreen_8(8, pcjr->firstline << 1, 0, (pcjr->lastline - pcjr->firstline) << 1, + video_blit_memtoscreen_8(8, pcjr->firstline << 1, xsize, (pcjr->lastline - pcjr->firstline) << 1); } } diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 75aa7cbeb..8de9883b7 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1032,17 +1032,17 @@ vid_poll(void *priv) if (enable_overscan) { if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, 0, ((vid->lastline - vid->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (vid->firstline - 4) << 1, xsize, ((vid->lastline - vid->firstline) + 8) << 1); } else { if (!dev->is_sl2 && vid->composite) - video_blit_memtoscreen(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); else - video_blit_memtoscreen_8(8, vid->firstline << 1, 0, (vid->lastline - vid->firstline) << 1, + video_blit_memtoscreen_8(8, vid->firstline << 1, xsize, (vid->lastline - vid->firstline) << 1); } } diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c new file mode 100644 index 000000000..85ddf68a7 --- /dev/null +++ b/src/machine/m_v86p.c @@ -0,0 +1,97 @@ +/* + * 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. + * + * Victor V86P portable computer emulation. + * + * Author: Lubomir Rintel, + * + * Copyright 2021 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include <86box/86box.h> +#include "cpu.h" +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/rom.h> +#include <86box/machine.h> +#include <86box/device.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/keyboard.h> +#include <86box/chipset.h> +#include <86box/sio.h> +#include <86box/video.h> + +int +machine_v86p_init(const machine_t *model) +{ + int ret, rom = 0; + + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", + 0x000f8000, 65536, 0); + + if (!ret) { + /* Try an older version of the BIOS. */ + rom = 1; + ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", + 0x000f8000, 65536, 0); + } + + if (!ret) { + /* Try JVERNET's BIOS. */ + rom = 2; + ret = bios_load_linear("roms/machines/v86p/V86P.ROM", + 0x000f0000, 65536, 0); + + } + + if (bios_only || !ret) + return ret; + + if (rom == 2) + loadfont("roms/machines/v86p/V86P.FON", 8); + else + loadfont("roms/machines/v86p/v86pfont.rom", 8); + + machine_common_init(model); + + device_add(&ct_82c100_device); + device_add(&f82c606_device); + + device_add(&keyboard_xt_device); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_xt_device); + + if (gfxcard == VID_INTERNAL) + device_add(&f82c425_video_device); + + return ret; +} diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 127495259..ce251eda7 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -424,3 +424,22 @@ machine_xt_pc700_init(const machine_t *model) return ret; } + + +int +machine_xt_multitechpc500_init(const machine_t* model) +{ + int ret; + + ret = bios_load_linear("roms/machines/multitech_pc500/rom404.bin", + 0x000f8000, 32768, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_pc_device); + + machine_xt_common_init(model); + + return ret; +} diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index c3930d29e..8e1c7029c 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -556,7 +556,7 @@ static void t1000_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; /* Fixed 640x200 resolution */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f8a4f3bb7..4f65bb383 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -72,7 +72,8 @@ 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] Eagle PC Spirit", "pcspirit", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pcspirit_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] Juko ST", "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-500", "multitech_pc500", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_multitechpc500_init, NULL }, { "[8088] Multitech PC-700", "pc700", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 64, 0, machine_xt_pc700_init, NULL }, { "[8088] NCR PC4i", "pc4i", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 256, 640, 256, 0, machine_xt_pc4i_init, NULL }, { "[8088] Olivetti M19", "m19", MACHINE_TYPE_8088, CPU_PKG_8088, 0, 4772728, 7159092, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 256, 640, 256, 0, machine_xt_m19_init, m19_get_device }, @@ -105,6 +106,7 @@ const machine_t machines[] = { { "[8086] Olivetti M240", "m240", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_m240_init, NULL }, { "[8086] Schetmash Iskra-3104", "iskra3104", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC, 128, 640, 128, 0, machine_xt_iskra3104_init, NULL }, { "[8086] Tandy 1000 SL/2", "tandy1000sl2", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, tandy1k_sl_get_device }, + { "[8086] Victor V86P", "v86p", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 512, 1024, 128, 127, machine_v86p_init, NULL }, { "[8086] Toshiba T1200", "t1200", MACHINE_TYPE_8086, CPU_PKG_8086, 0, 0, 0, 0, 0, 0, 0, MACHINE_PC | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) diff --git a/src/nmi.c b/src/nmi.c index 07742cefe..1e820a82a 100644 --- a/src/nmi.c +++ b/src/nmi.c @@ -20,6 +20,6 @@ void nmi_write(uint16_t port, uint8_t val, void *p) void nmi_init(void) { - io_sethandler(0x00a0, 0x0001, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); + io_sethandler(0x00a0, 0x000f, NULL, NULL, NULL, nmi_write, NULL, NULL, NULL); nmi_mask = 0; } diff --git a/src/nvr_at.c b/src/nvr_at.c index ff1c6fcb0..171a131cc 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -922,6 +922,13 @@ nvr_lock_set(int base, int size, int lock, nvr_t *nvr) } +void +nvr_irq_set(int irq, nvr_t *nvr) +{ + nvr->irq = irq; +} + + static void nvr_at_reset(void *priv) { diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c48af0ae5..2413c30a5 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1362,7 +1362,7 @@ t128_read(uint32_t addr, void *priv) if (ncr_dev->t128.host_pos == MIN(512, dev->buffer_length)) { ncr_dev->t128.status &= ~0x04; ncr_log("Transfer busy read, status = %02x, period = %lf\n", ncr_dev->t128.status, ncr_dev->period); - if (ncr_dev->period == 0.2) + if (ncr_dev->period == 0.2 || ncr_dev->period == 0.02) timer_on_auto(&ncr_dev->timer, 40.2); } } diff --git a/src/sio/sio_f82c710.c b/src/sio/sio_f82c710.c index 16b1fb4b2..6b866c094 100644 --- a/src/sio/sio_f82c710.c +++ b/src/sio/sio_f82c710.c @@ -6,13 +6,23 @@ * * This file is part of the 86Box distribution. * - * Implementation of the Chips & Technologies F82C710 Universal Peripheral Controller (UPC). + * Implementation of the Chips & Technologies F82C710 Universal Peripheral + * Controller (UPC) and 82C606 CHIPSpak Multifunction Controller. + * + * Relevant literature: + * + * [1] Chips and Technologies, Inc., + * 82C605/82C606 CHIPSpak/CHIPSport MULTIFUNCTION CONTROLLERS, + * PRELIMINARY Data Sheet, Revision 1, May 1987. + * * * Authors: Sarah Walker, * Eluan Costa Miranda + * Lubomir Rintel * * Copyright 2020 Sarah Walker. * Copyright 2020 Eluan Costa Miranda. + * Copyright 2021 Lubomir Rintel. */ #include #include @@ -25,213 +35,326 @@ #include <86box/device.h> #include <86box/lpt.h> #include <86box/serial.h> +#include <86box/gameport.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/nvr.h> #include <86box/sio.h> + typedef struct upc_t { - int configuration_state; /* state of algorithm to enter configuration mode */ - int configuration_mode; - uint16_t cri_addr; /* cri = configuration index register, addr is even */ - uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ - uint8_t cri; /* currently indexed register */ + uint32_t local; + int configuration_state; /* state of algorithm to enter configuration mode */ + int configuration_mode; + uint16_t cri_addr; /* cri = configuration index register, addr is even */ + uint16_t cap_addr; /* cap = configuration access port, addr is odd and is cri_addr + 1 */ + uint8_t cri; /* currently indexed register */ + uint8_t last_write; - /* these regs are not affected by reset */ - uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ - fdc_t *fdc; - serial_t *uart[2]; + /* these regs are not affected by reset */ + uint8_t regs[15]; /* there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode */ + fdc_t * fdc; + nvr_t * nvr; + void * gameport; + serial_t * uart[2]; } upc_t; + static void -f82c710_update_ports(upc_t *upc) +f82c710_update_ports(upc_t *dev, int set) { - uint16_t com_addr = 0; - uint16_t lpt_addr = 0; - - serial_remove(upc->uart[0]); - serial_remove(upc->uart[1]); - lpt1_remove(); - lpt2_remove(); - fdc_remove(upc->fdc); - ide_pri_disable(); + uint16_t com_addr = 0; + uint16_t lpt_addr = 0; - if (upc->regs[0] & 4) { - com_addr = upc->regs[4] * 4; - if (com_addr == SERIAL1_ADDR) { - serial_setup(upc->uart[0], com_addr, 4); - } else if (com_addr == SERIAL2_ADDR) { - serial_setup(upc->uart[1], com_addr, 3); - } - } - + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); + fdc_remove(dev->fdc); + ide_pri_disable(); - if (upc->regs[0] & 8) { - lpt_addr = upc->regs[6] * 4; - lpt1_init(lpt_addr); - if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) { - lpt1_irq(7); - } else if (lpt_addr == 0x278) { - lpt1_irq(5); - } - } + if (!set) + return; - if (upc->regs[12] & 0x80) { - ide_pri_enable(); - } + if (dev->regs[0] & 4) { + com_addr = dev->regs[4] * 4; + if (com_addr == SERIAL1_ADDR) + serial_setup(dev->uart[0], com_addr, 4); + else if (com_addr == SERIAL2_ADDR) + serial_setup(dev->uart[1], com_addr, 3); + } - if (upc->regs[12] & 0x20) { - fdc_set_base(upc->fdc, 0x03f0); - } + if (dev->regs[0] & 8) { + lpt_addr = dev->regs[6] * 4; + lpt1_init(lpt_addr); + if ((lpt_addr == 0x378) || (lpt_addr == 0x3bc)) + lpt1_irq(7); + else if (lpt_addr == 0x278) + lpt1_irq(5); + } + + if (dev->regs[12] & 0x80) + ide_pri_enable(); + + if (dev->regs[12] & 0x20) + fdc_set_base(dev->fdc, 0x03f0); } + +static void +f82c606_update_ports(upc_t *dev, int set) +{ + uint8_t uart1_int = 0xff; + uint8_t uart2_int = 0xff; + uint8_t lpt1_int = 0xff; + int nvr_int = -1; + + serial_remove(dev->uart[0]); + serial_remove(dev->uart[1]); + lpt1_remove(); + lpt2_remove(); + + nvr_at_handler(0, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_at_handler(0, 0x70, dev->nvr); + + gameport_remap(dev->gameport, 0); + + if (!set) + return; + + switch (dev->regs[8] & 0xc0) { + case 0x40: nvr_int = 3; break; + case 0x80: uart1_int = 3; break; + case 0xc0: uart2_int = 3; break; + } + + switch (dev->regs[8] & 0x30) { + case 0x10: nvr_int = 4; break; + case 0x20: uart1_int = 4; break; + case 0x30: uart2_int = 4; break; + } + + switch (dev->regs[8] & 0x0c) { + case 0x04: nvr_int = 5; break; + case 0x08: uart1_int = 5; break; + case 0x0c: lpt1_int = 5; break; + } + + switch (dev->regs[8] & 0x03) { + case 0x01: nvr_int = 7; break; + case 0x02: uart2_int = 7; break; + case 0x03: lpt1_int = 7; break; + } + + if (dev->regs[0] & 1) { + gameport_remap(dev->gameport, ((uint16_t) dev->regs[7]) << 2); + pclog("Game port at %04X\n", ((uint16_t) dev->regs[7]) << 2); + } + + if (dev->regs[0] & 2) { + serial_setup(dev->uart[0], ((uint16_t) dev->regs[4]) << 2, uart1_int); + pclog("UART 1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[4]) << 2, uart1_int); + } + + if (dev->regs[0] & 4) { + serial_setup(dev->uart[1], ((uint16_t) dev->regs[5]) << 2, uart2_int); + pclog("UART 2 at %04X, IRQ %i\n", ((uint16_t) dev->regs[5]) << 2, uart2_int); + } + + if (dev->regs[0] & 8) { + lpt1_init(((uint16_t) dev->regs[6]) << 2); + lpt1_irq(lpt1_int); + pclog("LPT1 at %04X, IRQ %i\n", ((uint16_t) dev->regs[6]) << 2, lpt1_int); + } + + nvr_at_handler(1, ((uint16_t) dev->regs[3]) << 2, dev->nvr); + nvr_irq_set(nvr_int, dev->nvr); + pclog("RTC at %04X, IRQ %i\n", ((uint16_t) dev->regs[3]) << 2, nvr_int); +} + + static uint8_t f82c710_config_read(uint16_t port, void *priv) { - upc_t *upc = (upc_t *)priv; - uint8_t temp = 0xff; + upc_t *dev = (upc_t *) priv; + uint8_t temp = 0xff; - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - temp = upc->cri; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) - temp = upc->cri_addr / 4; - else - temp = upc->regs[upc->cri]; - } - } + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + temp = dev->cri; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) + temp = dev->cri_addr / 4; + else + temp = dev->regs[dev->cri]; + } + } - return temp; + return temp; } + static void f82c710_config_write(uint16_t port, uint8_t val, void *priv) { - upc_t *upc = (upc_t *)priv; - int configuration_state_event = 0; + upc_t *dev = (upc_t *) priv; + int configuration_state_event = 0; - switch(port) { - case 0x2fa: - if (upc->configuration_state == 0 && val == 0x55) - configuration_state_event = 1; - else if (upc->configuration_state == 4) { - uint8_t addr_verify = upc->cri_addr / 4; - addr_verify += val; - if (addr_verify == 0xff) { - upc->configuration_mode = 1; - /* TODO: is the value of cri reset here or when exiting configuration mode? */ - io_sethandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - } else { - upc->configuration_mode = 0; - } - } - break; - case 0x3fa: - if (upc->configuration_state == 1 && val == 0xaa) - configuration_state_event = 1; - else if (upc->configuration_state == 2 && val == 0x36) - configuration_state_event = 1; - else if (upc->configuration_state == 3) { - upc->cri_addr = val * 4; - upc->cap_addr = upc->cri_addr + 1; - configuration_state_event = 1; - } - break; - default: - break; - } - - if (upc->configuration_mode) { - if (port == upc->cri_addr) { - upc->cri = val & 0xf; - } else if (port == upc->cap_addr) { - if (upc->cri == 0xf) { - upc->configuration_mode = 0; - io_removehandler(upc->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - f82c710_update_ports(upc); /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ - } else { - upc->regs[upc->cri] = val; - } - } - } + switch (port) { + case 0x2fa: + if ((dev->configuration_state == 0) && (val != 0x00) && (val != 0xff) && (dev->local == 606)) { + configuration_state_event = 1; + dev->last_write = val; + } else if ((dev->configuration_state == 0) && (val == 0x55) && (dev->local == 710)) + configuration_state_event = 1; + else if (dev->configuration_state == 4) { + if ((val | dev->last_write) == 0xff) { + dev->cri_addr = ((uint16_t) dev->last_write) << 2; + dev->cap_addr = dev->cri_addr + 1; + dev->configuration_mode = 1; + if (dev->local == 606) + f82c606_update_ports(dev, 0); + else if (dev->local == 710) + f82c710_update_ports(dev, 0); + /* TODO: is the value of cri reset here or when exiting configuration mode? */ + io_sethandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + } else + dev->configuration_mode = 0; + } + break; + case 0x3fa: + if ((dev->configuration_state == 1) && ((val | dev->last_write) == 0xff) && (dev->local == 606)) + configuration_state_event = 1; + else if ((dev->configuration_state == 1) && (val == 0xaa) && (dev->local == 710)) + configuration_state_event = 1; + else if ((dev->configuration_state == 2) && (val == 0x36)) + configuration_state_event = 1; + else if (dev->configuration_state == 3) { + dev->last_write = val; + configuration_state_event = 1; + } + break; + default: + break; + } - /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ - if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) - upc->configuration_state++; - else - upc->configuration_state = 0; + if (dev->configuration_mode) { + if (port == dev->cri_addr) { + dev->cri = val & 0xf; + } else if (port == dev->cap_addr) { + if (dev->cri == 0xf) { + dev->configuration_mode = 0; + io_removehandler(dev->cri_addr, 0x0002, f82c710_config_read, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + /* TODO: any benefit in updating at each register write instead of when exiting config mode? */ + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); + } else + dev->regs[dev->cri] = val; + } + } + + /* TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly? */ + if ((port == 0x2fa || port == 0x3fa) && configuration_state_event) + dev->configuration_state++; + else + dev->configuration_state = 0; } static void -f82c710_reset(upc_t *upc) +f82c710_reset(void *priv) { - serial_remove(upc->uart[0]); - serial_setup(upc->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + upc_t *dev = (upc_t *) priv; - serial_remove(upc->uart[1]); - serial_setup(upc->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); - - lpt1_remove(); - lpt1_init(0x378); - lpt1_irq(7); + /* Set power-on defaults. */ + if (dev->local == 606) { + dev->regs[0] = 0x00; /* Enable */ + dev->regs[1] = 0x00; /* Configuration Register */ + dev->regs[2] = 0x00; /* Ext Baud Rate Select */ + dev->regs[3] = 0xb0; /* RTC Base */ + dev->regs[4] = 0xfe; /* UART1 Base */ + dev->regs[5] = 0xbe; /* UART2 Base */ + dev->regs[6] = 0x9e; /* Parallel Base */ + dev->regs[7] = 0x80; /* Game Base */ + dev->regs[8] = 0xec; /* Interrupt Select */ + } else if (dev->local == 710) { + dev->regs[0] = 0x0c; + dev->regs[1] = 0x00; + dev->regs[2] = 0x00; + dev->regs[3] = 0x00; + dev->regs[4] = 0xfe; + dev->regs[5] = 0x00; + dev->regs[6] = 0x9e; + dev->regs[7] = 0x00; + dev->regs[8] = 0x00; + dev->regs[9] = 0xb0; + dev->regs[10] = 0x00; + dev->regs[11] = 0x00; + dev->regs[12] = 0xa0; + dev->regs[13] = 0x00; + dev->regs[14] = 0x00; + } - fdc_reset(upc->fdc); + if (dev->local == 606) + f82c606_update_ports(dev, 1); + else if (dev->local == 710) + f82c710_update_ports(dev, 1); } -static void * -f82c710_init(const device_t *info) -{ - upc_t *upc = (upc_t *) malloc(sizeof(upc_t)); - memset(upc, 0, sizeof(upc_t)); - - upc->fdc = device_add(&fdc_at_device); - - upc->uart[0] = device_add_inst(&ns16450_device, 1); - upc->uart[1] = device_add_inst(&ns16450_device, 2); - - io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, upc); - - upc->regs[0] = 0x0c; - upc->regs[1] = 0x00; - upc->regs[2] = 0x00; - upc->regs[3] = 0x00; - upc->regs[4] = 0xfe; - upc->regs[5] = 0x00; - upc->regs[6] = 0x9e; - upc->regs[7] = 0x00; - upc->regs[8] = 0x00; - upc->regs[9] = 0xb0; - upc->regs[10] = 0x00; - upc->regs[11] = 0x00; - upc->regs[12] = 0xa0; - upc->regs[13] = 0x00; - upc->regs[14] = 0x00; - - f82c710_reset(upc); - - f82c710_update_ports(upc); - - return upc; -} static void f82c710_close(void *priv) { - upc_t *upc = (upc_t *)priv; + upc_t *dev = (upc_t *) priv; - free(upc); + free(dev); } -const device_t f82c710_device = { - "F82C710 UPC Super I/O", - 0, - 0, - f82c710_init, f82c710_close, NULL, - { NULL }, NULL, NULL, - NULL + +static void * +f82c710_init(const device_t *info) +{ + upc_t *dev = (upc_t *) malloc(sizeof(upc_t)); + memset(dev, 0, sizeof(upc_t)); + dev->local = info->local; + + if (dev->local == 606) { + dev->nvr = device_add(&at_nvr_old_device); + dev->gameport = gameport_add(&gameport_sio_device); + } else if (dev->local == 710) + dev->fdc = device_add(&fdc_at_device); + + dev->uart[0] = device_add_inst(&ns16450_device, 1); + dev->uart[1] = device_add_inst(&ns16450_device, 2); + + io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, f82c710_config_write, NULL, NULL, dev); + + f82c710_reset(dev); + + return dev; +} + + +const device_t f82c606_device = { + "82C606 CHIPSpak Multifunction Controller", + 0, + 606, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL +}; + +const device_t f82c710_device = { + "F82C710 UPC Super I/O", + 0, + 710, + f82c710_init, f82c710_close, f82c710_reset, + { NULL }, NULL, NULL, + NULL }; diff --git a/src/thread.c b/src/thread.c new file mode 100644 index 000000000..d95c337d1 --- /dev/null +++ b/src/thread.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/plat.h> + + +typedef struct event_pthread_t +{ + pthread_cond_t cond; + pthread_mutex_t mutex; + int state; +} event_pthread_t; + + +typedef struct thread_param +{ + void (*thread_rout)(void*); + void * param; +} thread_param; + + +typedef struct pt_mutex_t +{ + pthread_mutex_t mutex; +} pt_mutex_t; + + +void * +thread_run_wrapper(thread_param* arg) +{ + thread_param localparam = *arg; + free(arg); + localparam.thread_rout(localparam.param); + return NULL; +} + + +thread_t * +thread_create(void (*thread_rout)(void *param), void *param) +{ + pthread_t *thread = malloc(sizeof(pthread_t)); + thread_param *thrparam = malloc(sizeof(thread_param)); + thrparam->thread_rout = thread_rout; + thrparam->param = param; + + pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); + + return thread; +} + + +int +thread_wait(thread_t *arg, int timeout) +{ + return pthread_join(*(pthread_t*)(arg), NULL) != 0; +} + + +event_t * +thread_create_event() +{ + event_pthread_t *event = malloc(sizeof(event_pthread_t)); + + pthread_cond_init(&event->cond, NULL); + pthread_mutex_init(&event->mutex, NULL); + event->state = 0; + + return (event_t *)event; +} + + +void +thread_set_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 1; + pthread_cond_broadcast(&event->cond); + pthread_mutex_unlock(&event->mutex); +} + + +void +thread_reset_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_mutex_lock(&event->mutex); + event->state = 0; + pthread_mutex_unlock(&event->mutex); +} + + +int +thread_wait_event(event_t *handle, int timeout) +{ + event_pthread_t *event = (event_pthread_t *)handle; + struct timespec abstime; + +#ifdef HAS_TIMESPEC_GET + timespec_get(&abstime, TIME_UTC); +#else + clock_gettime(CLOCK_REALTIME, &abstime); +#endif + abstime.tv_nsec += (timeout % 1000) * 1000000; + abstime.tv_sec += (timeout / 1000); + if (abstime.tv_nsec > 1000000000) { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec++; + } + + pthread_mutex_lock(&event->mutex); + if (timeout == -1) { + while (!event->state) + pthread_cond_wait(&event->cond, &event->mutex); + } else if (!event->state) + pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); + pthread_mutex_unlock(&event->mutex); + + return 0; +} + + +void +thread_destroy_event(event_t *handle) +{ + event_pthread_t *event = (event_pthread_t *)handle; + + pthread_cond_destroy(&event->cond); + pthread_mutex_destroy(&event->mutex); + + free(event); +} + + +mutex_t * +thread_create_mutex(void) +{ + pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); + + pthread_mutex_init(&mutex->mutex, NULL); + + return mutex; +} + + +mutex_t * +thread_create_mutex_with_spin_count(unsigned int spin_count) +{ + /* Setting spin count of a mutex is not possible with pthreads. */ + return thread_create_mutex(); +} + + +int +thread_wait_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return + pthread_mutex_lock(&mutex->mutex) != 0; +} + + +int +thread_release_mutex(mutex_t *_mutex) +{ + if (_mutex == NULL) + return(0); + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + return pthread_mutex_unlock(&mutex->mutex) != 0; +} + + +void +thread_close_mutex(mutex_t *_mutex) +{ + pt_mutex_t *mutex = (pt_mutex_t *)_mutex; + + pthread_mutex_destroy(&mutex->mutex); + + free(mutex); +} diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 2371124df..193de96c0 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -1,19 +1,17 @@ -set(PLAT_SOURCES unix_thread.c) if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") find_package(ALSA) if (ALSA_FOUND) - set(PLAT_SOURCES ${PLAT_SOURCES} linux_midi_alsa.c) + set(PLAT_SOURCES linux_midi_alsa.c) else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() else() - set(PLAT_SOURCES ${PLAT_SOURCES} unix_midi.c) + set(PLAT_SOURCES unix_midi.c) endif() add_library(plat STATIC ${PLAT_SOURCES}) add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c) target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64) target_link_libraries(ui dl) -target_link_libraries(plat pthread) if (ALSA_FOUND) target_link_libraries(plat ALSA::ALSA) endif() \ No newline at end of file diff --git a/src/unix/linux_midi_alsa.c b/src/unix/linux_midi_alsa.c index 2b771f81c..e3b009d6d 100644 --- a/src/unix/linux_midi_alsa.c +++ b/src/unix/linux_midi_alsa.c @@ -298,14 +298,17 @@ void plat_midi_input_init(void) void plat_midi_input_close(void) { - thread_wait_mutex(midiinmtx); + if (midiinmtx) thread_wait_mutex(midiinmtx); if (midiin != NULL) { snd_rawmidi_close(midiin); midiin = NULL; } - thread_release_mutex(midiinmtx); - thread_close_mutex(midiinmtx); + if (midiinmtx) + { + thread_release_mutex(midiinmtx); + thread_close_mutex(midiinmtx); + } midiinmtx = NULL; } diff --git a/src/unix/unix.c b/src/unix/unix.c index 4ce8d5e17..ca2866cb4 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -2,10 +2,7 @@ #define _FILE_OFFSET_BITS 64 #define _LARGEFILE64_SOURCE 1 #endif -#define _POSIX_C_SOURCE 200809L -#ifdef __APPLE__ -#define _DARWIN_C_SOURCE 1 -#endif +#include #include #include #include @@ -20,7 +17,7 @@ #include #include #include -#include + #include <86box/86box.h> #include <86box/keyboard.h> #include <86box/mouse.h> @@ -154,15 +151,20 @@ static const uint16_t sdl_to_xt[0x200] = [SDL_SCANCODE_KP_2] = 0x50, [SDL_SCANCODE_KP_1] = 0x4F, [SDL_SCANCODE_KP_0] = 0x52, - [SDL_SCANCODE_KP_PERIOD] = 0x53 + [SDL_SCANCODE_KP_PERIOD] = 0x53, + + [SDL_SCANCODE_LGUI] = 0x15B, + [SDL_SCANCODE_RGUI] = 0x15C, + [SDL_SCANCODE_APPLICATION] = 0x15D, + [SDL_SCANCODE_PRINTSCREEN] = 0x137 }; typedef struct sdl_blit_params { - int x, y, y1, y2, w, h; + int x, y, w, h; } sdl_blit_params; -sdl_blit_params params = { 0, 0, 0, 0, 0, 0 }; +sdl_blit_params params = { 0, 0, 0, 0 }; int blitreq = 0; void* dynld_module(const char *name, dllimp_t *table) @@ -605,7 +607,7 @@ void ui_sb_bugui(char *str) } -extern void sdl_blit(int x, int y, int y1, int y2, int w, int h); +extern void sdl_blit(int x, int y, int w, int h); typedef struct mouseinputdata { @@ -755,7 +757,26 @@ void monitor_thread(void* param) xargv[cmdargc++] = local_strsep(&linecpy, " "); if (xargv[cmdargc - 1] == NULL || cmdargc >= 512) break; } - if (strncasecmp(xargv[0], "exit", 4) == 0) + cmdargc--; + if (strncasecmp(xargv[0], "help", 4) == 0) + { + printf( + "fddload - Load floppy disk image into drive .\n" + "cdload - Load CD-ROM image into drive .\n" + "zipload - Load ZIP image into ZIP drive .\n" + "cartload - Load cartridge image into cartridge drive .\n" + "moload - Load MO image into MO drive .\n\n" + "fddeject - eject disk from floppy drive .\n" + "cdeject - eject disc from CD-ROM drive .\n" + "zipeject - eject ZIP image from ZIP drive .\n" + "carteject - eject cartridge from drive .\n" + "moeject - eject image from MO drive .\n\n" + "hardreset - hard reset the emulated system.\n" + "pause - pause the the emulated system.\n" + "fullscreen - toggle fullscreen.\n" + "exit - exit 86Box.\n"); + } + else if (strncasecmp(xargv[0], "exit", 4) == 0) { exit_event = 1; } @@ -1101,8 +1122,8 @@ int main(int argc, char** argv) } if (blitreq) { - extern void sdl_blit(int x, int y, int y1, int y2, int w, int h); - sdl_blit(params.x, params.y, params.y1, params.y2, params.w, params.h); + extern void sdl_blit(int x, int y, int w, int h); + sdl_blit(params.x, params.y, params.w, params.h); } if (title_set) { diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index e5abdcd32..ee1220409 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -23,7 +23,7 @@ typedef struct sdl_blit_params { - int x, y, y1, y2, w, h; + int x, y, w, h; } sdl_blit_params; extern sdl_blit_params params; extern int blitreq; @@ -121,26 +121,24 @@ sdl_stretch(int *w, int *h, int *x, int *y) void -sdl_blit_shim(int x, int y, int y1, int y2, int w, int h) +sdl_blit_shim(int x, int y, int w, int h) { params.x = x; params.y = y; params.w = w; params.h = h; - params.y1 = y1; - params.y2 = y2; blitreq = 1; } void ui_window_title_real(); void -sdl_blit(int x, int y, int y1, int y2, int w, int h) +sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (h <= 0) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } @@ -153,17 +151,17 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) else sdl_resize(resize_w, resize_h); resize_pending = 0; } - r_src.x = 0; - r_src.y = y1; + r_src.x = x; + r_src.y = y; r_src.w = w; - r_src.h = y2 - y1; - SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4); + r_src.h = h; + SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * 4); video_blit_complete(); SDL_RenderClear(sdl_render); - r_src.x = 0; - r_src.y = 0; + r_src.x = x; + r_src.y = y; r_src.w = w; r_src.h = h; @@ -367,7 +365,7 @@ sdl_init_common(int flags) } sdl_mutex = SDL_CreateMutex(); - sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL); + sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL | (vid_resize & 1 ? SDL_WINDOW_RESIZABLE : 0)); sdl_set_fs(video_fullscreen); if (!(video_fullscreen & 1)) { diff --git a/src/unix/unix_thread.c b/src/unix/unix_thread.c deleted file mode 100644 index 071178418..000000000 --- a/src/unix/unix_thread.c +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> - -typedef struct event_pthread_t -{ - pthread_cond_t cond; - pthread_mutex_t mutex; - int state; -} event_pthread_t; - -typedef struct thread_param -{ - void (*thread_rout)(void*); - void* param; -} thread_param; - -void* thread_run_wrapper(thread_param* arg) -{ - thread_param localparam = *arg; - free(arg); - localparam.thread_rout(localparam.param); - return NULL; -} - -thread_t *thread_create(void (*thread_rout)(void *param), void *param) -{ - pthread_t *thread = malloc(sizeof(pthread_t)); - thread_param *thrparam = malloc(sizeof(thread_param)); - thrparam->thread_rout = thread_rout; - thrparam->param = param; - - pthread_create(thread, NULL, (void* (*)(void*))thread_run_wrapper, thrparam); - - return thread; -} - -int -thread_wait(thread_t *arg, int timeout) -{ - return pthread_join(*(pthread_t*)(arg), NULL) != 0; -} - -event_t *thread_create_event() -{ - event_pthread_t *event = malloc(sizeof(event_pthread_t)); - - pthread_cond_init(&event->cond, NULL); - pthread_mutex_init(&event->mutex, NULL); - event->state = 0; - - return (event_t *)event; -} - -void thread_set_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 1; - pthread_cond_broadcast(&event->cond); - pthread_mutex_unlock(&event->mutex); -} - -void thread_reset_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_mutex_lock(&event->mutex); - event->state = 0; - pthread_mutex_unlock(&event->mutex); -} - -int thread_wait_event(event_t *handle, int timeout) -{ - event_pthread_t *event = (event_pthread_t *)handle; - struct timespec abstime; - -#if defined __linux__ || defined BSD - clock_gettime(CLOCK_REALTIME, &abstime); -#else - struct timeval now; - gettimeofday(&now, 0); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_usec*1000UL; -#endif - abstime.tv_nsec += (timeout % 1000) * 1000000; - abstime.tv_sec += (timeout / 1000); - if (abstime.tv_nsec > 1000000000) - { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec++; - } - - pthread_mutex_lock(&event->mutex); - if (timeout == -1) - { - while (!event->state) - pthread_cond_wait(&event->cond, &event->mutex); - } - else if (!event->state) - pthread_cond_timedwait(&event->cond, &event->mutex, &abstime); - pthread_mutex_unlock(&event->mutex); - - return 0; -} - -void thread_destroy_event(event_t *handle) -{ - event_pthread_t *event = (event_pthread_t *)handle; - - pthread_cond_destroy(&event->cond); - pthread_mutex_destroy(&event->mutex); - - free(event); -} - -void thread_sleep(int t) -{ - usleep(t * 1000); -} - - -typedef struct pt_mutex_t -{ - pthread_mutex_t mutex; -} pt_mutex_t; - -mutex_t *thread_create_mutex(void) -{ - pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t)); - - pthread_mutex_init(&mutex->mutex, NULL); - - return mutex; -} - -mutex_t * -thread_create_mutex_with_spin_count(unsigned int spin_count) -{ - /* Setting spin count of a mutex is not possible with pthreads. */ - return thread_create_mutex(); -} - -int thread_wait_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_lock(&mutex->mutex) != 0; -} - -int thread_release_mutex(mutex_t *_mutex) -{ - if (_mutex == NULL) return(0); - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - return pthread_mutex_unlock(&mutex->mutex) != 0; -} - -void thread_close_mutex(mutex_t *_mutex) -{ - pt_mutex_t *mutex = (pt_mutex_t *)_mutex; - - pthread_mutex_destroy(&mutex->mutex); - - free(mutex); -} \ No newline at end of file diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 4cbc18535..50572dbd8 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(vid OBJECT video.c vid_table.c vid_cga.c vid_cga_comp.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c vid_rtg310x.c - vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c + vid_f82c425.c vid_ti_cf62011.c vid_tvga.c vid_tgui9440.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_nga.c vid_tvp3026_ramdac.c) diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index dda14f48e..ef3f2c4ef 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -463,17 +463,17 @@ cga_poll(void *p) if (enable_overscan) { if (cga->composite) - video_blit_memtoscreen(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + video_blit_memtoscreen(0, (cga->firstline - 4) << 1, xsize, ((cga->lastline - cga->firstline) + 8) << 1); else - video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, 0, ((cga->lastline - cga->firstline) + 8) << 1, + video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1, xsize, ((cga->lastline - cga->firstline) + 8) << 1); } else { if (cga->composite) - video_blit_memtoscreen(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen(8, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); else - video_blit_memtoscreen_8(8, cga->firstline << 1, 0, (cga->lastline - cga->firstline) << 1, + video_blit_memtoscreen_8(8, cga->firstline << 1, xsize, (cga->lastline - cga->firstline) << 1); } } diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index ed5cd6f00..3343aaf0e 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -326,9 +326,9 @@ void colorplus_poll(void *p) } if (colorplus->cga.composite) - video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); + video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); else - video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); + video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); frames++; video_res_x = xsize - 16; diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index 0a82bdee1..d971a6af4 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -340,14 +340,14 @@ compaq_cga_poll(void *p) if (enable_overscan) { if (self->cga.composite) - video_blit_memtoscreen(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16); + video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, self->cga.firstline - 8, 0, (self->cga.lastline - self->cga.firstline) + 16, xsize, (self->cga.lastline - self->cga.firstline) + 16); + video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16); } else { if (self->cga.composite) - video_blit_memtoscreen(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); else - video_blit_memtoscreen_8(8, self->cga.firstline, 0, self->cga.lastline - self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); + video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline); } } diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 570a676d3..61cf87ee0 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -35,7 +35,7 @@ #include <86box/vid_ega.h> -void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega); +void ega_doblit(int wx, int wy, ega_t *ega); #define BIOS_IBM_PATH "roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" @@ -597,10 +597,10 @@ ega_poll(void *p) if (ega->vres) { wy = (ega->lastline - ega->firstline) << 1; - ega_doblit(ega->firstline_draw << 1, (ega->lastline_draw + 1) << 1, wx, wy, ega); + ega_doblit(wx, wy, ega); } else { wy = ega->lastline - ega->firstline; - ega_doblit(ega->firstline_draw, ega->lastline_draw + 1, wx, wy, ega); + ega_doblit(wx, wy, ega); } frames++; @@ -658,7 +658,7 @@ ega_poll(void *p) void -ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) +ega_doblit(int wx, int wy, ega_t *ega) { int y_add = (enable_overscan) ? overscan_y : 0; int x_add = (enable_overscan) ? overscan_x : 0; @@ -675,15 +675,8 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) bottom <<= 1; } - if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); + if ((wx <= 0) || (wy <= 0)) return; - } - - if (y1 > y2) { - video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); - return; - } if (ega->vres) ega->y_add <<= 1; @@ -734,7 +727,7 @@ ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega) } } - video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); if (ega->vres) ega->y_add >>= 1; diff --git a/src/video/vid_f82c425.c b/src/video/vid_f82c425.c new file mode 100644 index 000000000..e2f2f0677 --- /dev/null +++ b/src/video/vid_f82c425.c @@ -0,0 +1,672 @@ +/* + * 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. + * + * Chips & Technologies 82C425 display controller emulation, + * with support for 640x200 LCD and SMARTMAP text contrast + * enhancement. + * + * Relevant literature: + * + * [1] Chips and Technologies, Inc., 82C425 CGA LCD/CRT Controller, + * Data Sheet, Revision No. 2.2, September 1991. + * + * + * [2] Pleva et al., COLOR TO MONOCHROME CONVERSION, + * U.S. Patent 4,977,398, Dec. 11, 1990. + * + * + * Based on Toshiba T1000 plasma display emulation code. + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * Lubomir Rintel, + * + * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2018,2019 Miran Grca. + * Copyright 2018,2019 Sarah Walker. + * Copyright 2021 Lubomir Rintel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include "cpu.h" +#include <86box/video.h> +#include <86box/vid_cga.h> + +#define F82C425_XSIZE 640 +#define F82C425_YSIZE 200 + +/* Mapping of attributes to colours */ +static uint32_t smartmap[256][2]; +static uint32_t colormap[4]; + +static video_timings_t timing_f82c425 = {VIDEO_ISA, 8,16,32, 8,16,32}; + +static uint8_t st_video_options; +static uint8_t st_enabled = 1; +static int8_t st_display_internal = -1; + +void f82c425_video_options_set(uint8_t options) +{ + st_video_options = options; +} + +void f82c425_video_enable(uint8_t enabled) +{ + st_enabled = enabled; +} + +void f82c425_display_set(uint8_t internal) +{ + st_display_internal = (int8_t)internal; +} + +uint8_t f82c425_display_get() +{ + return (uint8_t)st_display_internal; +} + + +typedef struct f82c425_t +{ + mem_mapping_t mapping; + cga_t cga; + uint8_t crtcreg; + + uint64_t dispontime, dispofftime; + + int linepos, displine; + int dispon; + uint8_t video_options; + + uint8_t *vram; + + /* Registers specific to 82C425. */ + uint8_t ac_limit; + uint8_t threshold; + uint8_t shift; + uint8_t hsync; + uint8_t vsync_blink; + uint8_t timing; + uint8_t function; +} f82c425_t; + + +/* Convert IRGB representation to RGBI, + * useful in SMARTMAP calculations. */ +static inline uint8_t f82c425_rgbi(uint8_t irgb) +{ + return ((irgb & 0x7) << 1) | (irgb >> 3); +} + +/* Convert IRGB SMARTMAP output to a RGB representation of one of 4/8 grey + * shades we'd see on an actual V86P display: with some bias toward lighter + * shades and a backlight with yellow/green-ish tint. */ +static inline uint32_t f82c425_makecol(uint8_t rgbi, int gs4, int inv) +{ + uint8_t c; + + gs4 = 1 + !!gs4; + if (!inv) + { + rgbi = 15 - rgbi; + } + c = 0x10 * gs4 * ((rgbi >> gs4) + 2); + +#ifdef NO_BLUE + return makecol(c, c + 0x08, c - 0x20); +#else + return makecol(c, c + 0x08, 0x70); +#endif +} + +/* Saturating/non-saturating addition for SMARTMAP(see below). */ +static inline int f82c425_smartmap_add(int a, int b, int sat) +{ + int c = a + b; + + /* (SATURATING OR NON SATURATING) */ + if (sat) + { + if (c < 0) + c = 0; + else if (c > 15) + c = 15; + } + + return c & 0xf; +} + +/* Calculate and cache mapping of CGA text color attribute to a + * shade of gray enhanced via the SMARTMAP algorithm. + * + * This is a straightforward implementation of the algorithm as described + * in U.S. Patent 4,977,398 [2]. The comments in capitals refer to portions + * of a figure on page 4. */ +static void f82c425_smartmap(f82c425_t *f82c425) +{ + int i; + + for (i = 0; i < 256; i++) { + uint8_t bg = f82c425_rgbi(i >> 4); + uint8_t fg = f82c425_rgbi(i & 0xf); + + /* FIG._4. */ + if (abs(bg - fg) <= (f82c425->threshold & 0x0f)) + { + /* FOREGROUND=BACKGROUND */ + if (bg == fg) + { + /* SPECIAL CASE */ + if (f82c425->shift == 0xff) + { + /* CHECK MOST SIGNIFICANT BIT */ + if (fg & 0x8) + { + /* FULL WHITE */ + fg = bg = 15; + } + else + { + /* FULL BLACK */ + fg = bg = 0; + } + } + } + else + { + uint8_t sat = f82c425->threshold & 0x10; + + /* DETERMINE WHICH IS LIGHT */ + if (fg > bg) + { + fg = f82c425_smartmap_add(fg, f82c425->shift & 0x0f, sat); + bg = f82c425_smartmap_add(bg, -(f82c425->shift >> 4), sat); + } + else + { + fg = f82c425_smartmap_add(fg, -(f82c425->shift & 0x0f), sat); + bg = f82c425_smartmap_add(bg, f82c425->shift >> 4, sat); + } + } + } + + smartmap[i][0] = f82c425_makecol(bg, f82c425->threshold & 0x20, f82c425->function & 0x80); + smartmap[i][1] = f82c425_makecol(fg, f82c425->threshold & 0x20, f82c425->function & 0x80); + } +} + +/* Calculate mapping of 320x200 graphical mode colors. */ +static void f82c425_colormap(f82c425_t *f82c425) +{ + int i; + + for (i = 0; i < 4; i++) + colormap[i] = f82c425_makecol(5 * i, 0, f82c425->function & 0x80); +} + +static void f82c425_out(uint16_t addr, uint8_t val, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if (addr == 0x3d4) + f82c425->crtcreg = val; + + if (((f82c425->function & 0x01) == 0) && ((f82c425->crtcreg != 0xdf) || (addr != 0x3d5))) + return; + + if (addr != 0x3d5 || f82c425->crtcreg <= 31) + { + cga_out(addr, val, &f82c425->cga); + return; + } + + switch (f82c425->crtcreg) + { + case 0xd9: + f82c425->ac_limit = val; + break; + case 0xda: + f82c425->threshold = val; + f82c425_smartmap(f82c425); + break; + case 0xdb: + f82c425->shift = val; + f82c425_smartmap(f82c425); + break; + case 0xdc: + f82c425->hsync = val; + break; + case 0xdd: + f82c425->vsync_blink = val; + break; + case 0xde: + f82c425->timing = val; + break; + case 0xdf: + f82c425->function = val; + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); + break; + } +} + +static uint8_t f82c425_in(uint16_t addr, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if ((f82c425->function & 0x01) == 0) + return 0xff; + + if (addr == 0x3d4) + return f82c425->crtcreg; + + if (addr != 0x3d5 || f82c425->crtcreg <= 31) + return cga_in(addr, &f82c425->cga); + + switch (f82c425->crtcreg) + { + case 0xd9: + return f82c425->ac_limit; + case 0xda: + return f82c425->threshold; + case 0xdb: + return f82c425->shift; + case 0xdc: + return f82c425->hsync; + case 0xdd: + return f82c425->vsync_blink; + case 0xde: + return f82c425->timing; + case 0xdf: + return f82c425->function; + } + + return 0xff; +} + +static void f82c425_write(uint32_t addr, uint8_t val, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + f82c425->vram[addr & 0x3fff] = val; + cycles -= 4; +} + +static uint8_t f82c425_read(uint32_t addr, void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + cycles -= 4; + + return f82c425->vram[addr & 0x3fff]; +} + +static void f82c425_recalctimings(f82c425_t *f82c425) +{ + double disptime; + double _dispontime, _dispofftime; + + if (f82c425->function & 0x08) + { + cga_recalctimings(&f82c425->cga); + return; + } + + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; + f82c425->dispontime = (uint64_t)(_dispontime * xt_cpu_multi); + f82c425->dispofftime = (uint64_t)(_dispofftime * xt_cpu_multi); +} + +/* Draw a row of text. */ +static void f82c425_text_row(f82c425_t *f82c425) +{ + uint32_t colors[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int blink; + uint16_t addr; + uint8_t sc; + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff; + uint8_t sl = f82c425->cga.crtc[9] + 1; + int columns = f82c425->cga.crtc[1]; + + sc = (f82c425->displine) & 7; + addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2; + ma += (f82c425->displine >> 3) * columns; + + if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) + { + cursorline = 0; + } + else + { + cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && + ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc); + } + + for (x = 0; x < columns; x++) + { + chr = f82c425->vram[(addr + 2 * x) & 0x3FFF]; + attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && + (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10)); + + blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (drawcursor) + { + colors[0] = smartmap[~attr & 0xff][0]; + colors[1] = smartmap[~attr & 0xff][1]; + } + else + { + colors[0] = smartmap[attr][0]; + colors[1] = smartmap[attr][1]; + } + + if (blink) + colors[1] = colors[0]; + + if (f82c425->cga.cgamode & 0x01) + { + /* High resolution (80 cols) */ + for (c = 0; c < sl; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 3) + c] = + colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; + } + } + else + { + /* Low resolution (40 columns, stretch pixels horizontally) */ + for (c = 0; c < sl; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2] = + ((uint32_t *)buffer32->line[f82c425->displine])[(x << 4) + c*2+1] = + colors[(fontdat[chr][sc] & (1 <<(c ^ 7))) ? 1 : 0]; + } + } + + ++ma; + } +} + +/* Draw a line in CGA 640x200 mode */ +static void f82c425_cgaline6(f82c425_t *f82c425) +{ + int x, c; + uint8_t dat; + uint16_t addr; + + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + + addr = ((f82c425->displine) & 1) * 0x2000 + + (f82c425->displine >> 1) * 80 + + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) + { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 8; c++) + { + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+c] = + colormap[dat & 0x80 ? 3 : 0]; + + dat = dat << 1; + } + } +} + +/* Draw a line in CGA 320x200 mode. */ +static void f82c425_cgaline4(f82c425_t *f82c425) +{ + int x, c; + uint8_t dat, pattern; + uint16_t addr; + + uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff; + addr = ((f82c425->displine) & 1) * 0x2000 + + (f82c425->displine >> 1) * 80 + + ((ma & ~1) << 1); + + for (x = 0; x < 80; x++) + { + dat = f82c425->vram[addr & 0x3FFF]; + addr++; + + for (c = 0; c < 4; c++) + { + pattern = (dat & 0xC0) >> 6; + if (!(f82c425->cga.cgamode & 0x08)) pattern = 0; + + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c] = + ((uint32_t *)buffer32->line[f82c425->displine])[x*8+2*c+1] = + colormap[pattern & 3]; + + dat = dat << 2; + } + } +} + +static void f82c425_poll(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + if (f82c425->video_options != st_video_options || + !!(f82c425->function & 1) != st_enabled) + { + f82c425->video_options = st_video_options; + f82c425->function &= ~1; + f82c425->function |= st_enabled ? 1 : 0; + + if (f82c425->function & 0x01) + mem_mapping_enable(&f82c425->mapping); + else + mem_mapping_disable(&f82c425->mapping); + } + /* Switch between internal LCD and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != !!(f82c425->function & 0x08)) + { + if (st_display_internal) + { + f82c425->function &= ~0x08; + f82c425->timing &= ~0x20; + } + else + { + f82c425->function |= 0x08; + f82c425->timing |= 0x20; + } + f82c425_recalctimings(f82c425); + } + + if (f82c425->function & 0x08) + { + cga_poll(&f82c425->cga); + return; + } + + if (!f82c425->linepos) + { + timer_advance_u64(&f82c425->cga.timer, f82c425->dispofftime); + f82c425->cga.cgastat |= 1; + f82c425->linepos = 1; + if (f82c425->dispon) + { + if (f82c425->displine == 0) + { + video_wait_for_buffer(); + } + + switch (f82c425->cga.cgamode & 0x13) + { + case 0x12: + f82c425_cgaline6(f82c425); + break; + case 0x02: + f82c425_cgaline4(f82c425); + break; + case 0x00: + case 0x01: + f82c425_text_row(f82c425); + break; + } + } + f82c425->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (f82c425->displine >= 216) + { + /* End of VSYNC */ + f82c425->displine = 0; + f82c425->cga.cgastat &= ~8; + f82c425->dispon = 1; + } + else + if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) + { + /* Start of VSYNC */ + f82c425->cga.cgastat |= 8; + f82c425->dispon = 0; + } + } + else + { + if (f82c425->dispon) + f82c425->cga.cgastat &= ~1; + timer_advance_u64(&f82c425->cga.timer, f82c425->dispontime); + f82c425->linepos = 0; + + if (f82c425->displine == 200) + { + /* Hardcode 640x200 window size */ + if ((F82C425_XSIZE != xsize) || (F82C425_YSIZE != ysize) || video_force_resize_get()) + { + xsize = F82C425_XSIZE; + ysize = F82C425_YSIZE; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, 0, xsize, ysize); + frames++; + + /* Fixed 640x200 resolution */ + video_res_x = F82C425_XSIZE; + video_res_y = F82C425_YSIZE; + + switch (f82c425->cga.cgamode & 0x12) + { + case 0x12: + video_bpp = 1; + break; + case 0x02: + video_bpp = 2; + break; + default: + video_bpp = 0; + } + + f82c425->cga.cgablink++; + } + } +} + +static void *f82c425_init(const device_t *info) +{ + f82c425_t *f82c425 = malloc(sizeof(f82c425_t)); + memset(f82c425, 0, sizeof(f82c425_t)); + cga_init(&f82c425->cga); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_f82c425); + + /* Initialize registers that don't default to zero. */ + f82c425->hsync = 0x40; + f82c425->vsync_blink = 0x72; + + /* 16k video RAM */ + f82c425->vram = malloc(0x4000); + + timer_set_callback(&f82c425->cga.timer, f82c425_poll); + timer_set_p(&f82c425->cga.timer, f82c425); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_mapping_add(&f82c425->mapping, 0xb8000, 0x8000, f82c425_read, NULL, NULL, f82c425_write, NULL, NULL, NULL, 0, f82c425); + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 0x000c, f82c425_in, NULL, NULL, f82c425_out, NULL, NULL, f82c425); + + /* Initialize color maps for text & graphic modes */ + f82c425_smartmap(f82c425); + f82c425_colormap(f82c425); + + /* Start off in 80x25 text mode */ + f82c425->cga.cgastat = 0xF4; + f82c425->cga.vram = f82c425->vram; + f82c425->video_options = 0x01; + + return f82c425; +} + +static void f82c425_close(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + free(f82c425->vram); + free(f82c425); +} + +static void f82c425_speed_changed(void *p) +{ + f82c425_t *f82c425 = (f82c425_t *)p; + + f82c425_recalctimings(f82c425); +} + +const device_t f82c425_video_device = { + "82C425 CGA LCD/CRT Controller", + 0, 0, + f82c425_init, f82c425_close, NULL, + { NULL }, + f82c425_speed_changed, + NULL, + NULL +}; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index c054230b1..57854a051 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -689,7 +689,7 @@ genius_poll(void *p) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* Fixed 728x1008 resolution */ diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index 650d9e5b0..6c9660bb8 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -279,11 +279,17 @@ static void hercules_render_overscan_left(hercules_t *dev) { int i; + uint32_t width; + + if (dev->ctrl & 0x02) + width = (((uint32_t) dev->crtc[1]) << 4); + else + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) return; - if ((((uint32_t) dev->crtc[1]) * 9) == 0) + if (width == 0) return; for (i = 0; i < 8; i++) @@ -295,15 +301,21 @@ static void hercules_render_overscan_right(hercules_t *dev) { int i; + uint32_t width; + + if (dev->ctrl & 0x02) + width = (((uint32_t) dev->crtc[1]) << 4); + else + width = (((uint32_t) dev->crtc[1]) * 9); if ((dev->displine + 14) < 0) return; - if ((((uint32_t) dev->crtc[1]) * 9) == 0) + if (width == 0) return; for (i = 0; i < 8; i++) - buffer32->line[dev->displine + 14][8 + (((uint32_t) dev->crtc[1]) * 9) + i] = 0x00000000; + buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000; } @@ -505,9 +517,9 @@ hercules_poll(void *priv) } if (enable_overscan) - video_blit_memtoscreen_8(0, dev->firstline, 0, ysize + 28, xsize + 16, ysize + 28); + video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28); else - video_blit_memtoscreen_8(8, dev->firstline + 14, 0, ysize + 14, xsize, ysize); + video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize); frames++; // if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { if (dev->ctrl & 0x02) { diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index df5b01da0..607780a68 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -581,7 +581,7 @@ herculesplus_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + video_blit_memtoscreen_8(0, dev->firstline, xsize, dev->lastline - dev->firstline); frames++; if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { video_res_x = dev->crtc[1] * 16; diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index eafc7400c..3f12bdfdc 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -649,7 +649,9 @@ ht216_recalctimings(svga_t *svga) svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; svga->rowoffset <<= 1; if ((svga->crtc[0x17] & 0x60) == 0x20) /*Would result in a garbled screen with trailing cursor glitches*/ - svga->crtc[0x17] |= 0x40; + svga->force_byte_mode = 1; + else + svga->force_byte_mode = 0; } svga->render = svga_render_8bpp_highres; } diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index 8b644077e..64d93a5c0 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -998,7 +998,7 @@ incolor_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline); frames++; if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { video_res_x = dev->crtc[1] * 16; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index c05744b01..f2550f134 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -230,7 +230,7 @@ void mda_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, mda->firstline, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize); frames++; video_res_x = mda->crtc[1]; video_res_y = mda->crtc[6]; diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 66c09d744..1c34db342 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -474,17 +474,17 @@ nga_poll(void *priv) /* nga specific */ if (enable_overscan) { if (nga->cga.composite) - video_blit_memtoscreen(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16, + video_blit_memtoscreen(0, (nga->cga.firstline - 8), xsize, (nga->cga.lastline - nga->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), 0, (nga->cga.lastline - nga->cga.firstline) + 16, + video_blit_memtoscreen_8(0, (nga->cga.firstline - 8), xsize, (nga->cga.lastline - nga->cga.firstline) + 16); } else { if (nga->cga.composite) - video_blit_memtoscreen(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline), + video_blit_memtoscreen(8, nga->cga.firstline, xsize, (nga->cga.lastline - nga->cga.firstline)); else - video_blit_memtoscreen_8(8, nga->cga.firstline, 0, (nga->cga.lastline - nga->cga.firstline), + video_blit_memtoscreen_8(8, nga->cga.firstline, xsize, (nga->cga.lastline - nga->cga.firstline)); } } diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index cdc433bdf..c562c6f11 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -489,17 +489,17 @@ ogc_poll(void *priv) /* ogc specific */ if (enable_overscan) { if (ogc->cga.composite) - video_blit_memtoscreen(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16, + video_blit_memtoscreen(0, (ogc->cga.firstline - 8), xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); else - video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), 0, (ogc->cga.lastline - ogc->cga.firstline) + 16, + video_blit_memtoscreen_8(0, (ogc->cga.firstline - 8), xsize, (ogc->cga.lastline - ogc->cga.firstline) + 16); } else { if (ogc->cga.composite) - video_blit_memtoscreen(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline), + video_blit_memtoscreen(8, ogc->cga.firstline, xsize, (ogc->cga.lastline - ogc->cga.firstline)); else - video_blit_memtoscreen_8(8, ogc->cga.firstline, 0, (ogc->cga.lastline - ogc->cga.firstline), + video_blit_memtoscreen_8(8, ogc->cga.firstline, xsize, (ogc->cga.lastline - ogc->cga.firstline)); } } diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index 213d85f6a..34e5c2d99 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2493,7 +2493,7 @@ pgc_cga_poll(pgc_t *dev) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* We have a fixed 640x400 screen for CGA modes. */ @@ -2578,7 +2578,7 @@ pgc_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, xsize, ysize); frames++; video_res_x = dev->screenw; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index d3fb9c468..a5e635a99 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -43,9 +43,11 @@ #define ROM_METHEUS_86C928 "roms/video/s3/928.vbi" #define ROM_SPEA_MIRAGE_86C801 "roms/video/s3/V7MIRAGE.VBI" #define ROM_SPEA_MIRAGE_86C805 "roms/video/s3/86c805pspeavlbus.BIN" +#define ROM_MIROCRYSTAL8S_805 "roms/video/s3/S3_805VL_ATT20C491_miroCRYSTAL_8s_ver1.4.BIN" #define ROM_MIROCRYSTAL10SD_805 "roms/video/s3/MIROcrystal10SD_VLB.VBI" #define ROM_MIROCRYSTAL20SV_964_VLB "roms/video/s3/S3_964VL_BT485_27C256_miroCRYSTAL_20sv_ver1.2.bin" #define ROM_MIROCRYSTAL20SV_964_PCI "roms/video/s3/mirocrystal.VBI" +#define ROM_MIROCRYSTAL20SD_864_VLB "roms/video/s3/Miro20SD.BIN" #define ROM_PHOENIX_86C80X "roms/video/s3/805.vbi" #define ROM_PARADISE_BAHAMAS64 "roms/video/s3/bahamas64.bin" #define ROM_PHOENIX_VISION864 "roms/video/s3/86c864p.bin" @@ -61,8 +63,9 @@ #define ROM_ELSAWIN2KPROX_964 "roms/video/s3/elsaw20004m.BIN" #define ROM_ELSAWIN2KPROX "roms/video/s3/elsaw20008m.BIN" #define ROM_PHOENIX_VISION868 "roms/video/s3/1-DSV3868.BIN" -#define ROM_MIROVIDEO40SV_968 "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" +#define ROM_MIROVIDEO40SV_ERGO_968_PCI "roms/video/s3/S3_968PCI_TVP3026_miroVideo40SV_PCI_1.04.BIN" #define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" +#define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" enum { @@ -89,11 +92,14 @@ enum S3_ELSAWIN2KPROX_964, S3_ELSAWIN2KPROX, S3_PHOENIX_VISION868, - S3_MIROVIDEO40SV_968, + S3_MIROVIDEO40SV_ERGO_968, S3_MIROCRYSTAL10SD_805, S3_SPEA_MIRAGE_P64, S3_SPEA_MERCURY_P64V, - S3_MIROCRYSTAL20SV_964 + S3_MIROCRYSTAL20SV_964, + S3_MIROCRYSTAL20SD_864, + S3_PHOENIX_VISION968, + S3_MIROCRYSTAL8S_805 }; @@ -250,9 +256,15 @@ typedef struct s3_t int dat_count; int b2e8_pix, temp_cnt; uint8_t cur_x_bit12, cur_y_bit12; - int ssv_len1, ssv_len2; - uint8_t ssv_dir1, ssv_dir2; - uint8_t ssv_draw1, ssv_draw2; + int ssv_len; + uint8_t ssv_dir; + uint8_t ssv_draw; + + /*For non-threaded FIFO*/ + int setup_fifo_slot; + int draw_fifo_slot; + int setup_fifo, setup_fifo2; + int draw_fifo, draw_fifo2; } accel; struct { @@ -373,19 +385,36 @@ static uint32_t s3_accel_in_l(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) +/*Remap address for chain-4/doubleword style layout*/ +static __inline uint32_t +dword_remap(svga_t *svga, uint32_t in_addr) { - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0x3fff0) | + ((in_addr >> 14) & 0xc) | + (in_addr & ~0x3fffc); } - -static void -s3_wait_fifo_idle(s3_t *s3) +static __inline uint32_t +dword_remap_w(svga_t *svga, uint32_t in_addr) { - while (!FIFO_EMPTY) { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0x1fff8) | + ((in_addr >> 14) & 0x6) | + (in_addr & ~0x1fffe); +} +static __inline uint32_t +dword_remap_l(svga_t *svga, uint32_t in_addr) +{ + if (svga->packed_chain4) + return in_addr; + + return ((in_addr << 2) & 0xfffc) | + ((in_addr >> 14) & 0x3) | + (in_addr & ~0xffff); } static void @@ -402,6 +431,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); +void s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv); static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); #define WRITE8(addr, var, val) switch ((addr) & 3) \ @@ -471,43 +501,65 @@ s3_cpu_dest(s3_t *s3) static int s3_enable_fifo(s3_t *s3) { + svga_t *svga = &s3->svga; + 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_VISION868)) return 1; /* FIFO always enabled on these chips. */ - //return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); - return 0; /*Disable FIFO on pre-964 cards due to glitches going around*/ + return !!((svga->crtc[0x40] & 0x08) || (s3->accel.advfunc_cntl & 0x40)); } static void s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) { svga_t *svga = &s3->svga; - + if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(16, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); break; case 0x400: if (svga->crtc[0x53] & 0x08) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(32, 1, val | (val << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(32, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); + } else { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } else s3_accel_start(4, 1, 0xffffffff, val | (val << 16), s3); } @@ -515,10 +567,12 @@ s3_accel_out_pixtrans_w(s3_t *s3, uint16_t val) case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = (val >> 8) | (val << 8); - s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); - s3_accel_start(8, 1, val & 0xff, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } } } break; @@ -533,21 +587,31 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } } else { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); } break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, val, s3); s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); @@ -555,21 +619,26 @@ s3_accel_out_pixtrans_l(s3_t *s3, uint32_t val) break; case 0x400: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } else + s3_accel_start(4, 1, 0xffffffff, val, s3); } else s3_accel_start(4, 1, 0xffffffff, val, s3); break; case 0x600: if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if ((s3->accel.cmd & 0x1000) && (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40))) - 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); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + 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); + } } } break; @@ -584,6 +653,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (port) { case 0x8148: case 0x82e8: + s3->accel.draw_fifo_slot++; s3->accel.cur_y_bitres = (s3->accel.cur_y_bitres & 0xff00) | val; s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; s3->accel.poly_cy = s3->accel.cur_y; @@ -595,6 +665,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_cy = s3->accel.cur_y; break; case 0x814a: case 0x82ea: + s3->accel.draw_fifo_slot++; s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; s3->accel.poly_cy2 = s3->accel.cur_y2; break; @@ -604,6 +675,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8548: case 0x86e8: + s3->accel.draw_fifo_slot++; s3->accel.cur_x_bitres = (s3->accel.cur_x_bitres & 0xff00) | val; s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; s3->accel.poly_cx = s3->accel.cur_x << 20; @@ -617,6 +689,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.poly_x = s3->accel.poly_cx >> 20; break; case 0x854a: case 0x86ea: + s3->accel.draw_fifo_slot++; s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; break; @@ -626,6 +699,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8948: case 0x8ae8: + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -636,6 +710,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x894a: case 0x8aea: + s3->accel.draw_fifo_slot++; s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; s3->accel.point_2_updated = 1; break; @@ -647,6 +722,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x8d48: case 0x8ee8: + s3->accel.draw_fifo_slot++; s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; s3->accel.point_1_updated = 1; break; @@ -657,6 +733,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.point_1_updated = 1; break; case 0x8d4a: case 0x8eea: + s3->accel.draw_fifo_slot++; s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; s3->accel.point_2_updated = 1; break; @@ -666,6 +743,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9148: case 0x92e8: + s3->accel.draw_fifo_slot++; s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; break; case 0x9149: case 0x92e9: @@ -683,6 +761,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9548: case 0x96e8: + s3->accel.draw_fifo_slot++; s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xf00) | val; break; case 0x9459: case 0x96e9: @@ -700,6 +779,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0x9948: case 0x9ae8: + s3->accel.draw_fifo_slot++; s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; s3->data_available = 0; s3->accel.b2e8_pix = 0; @@ -722,13 +802,25 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; break; case 0x9d49: case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); s3->accel.ssv_state = 1; - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } break; case 0xa148: case 0xa2e8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); else @@ -765,6 +857,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa548: case 0xa6e8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); else @@ -801,6 +894,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa948: case 0xaae8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); else @@ -837,6 +931,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xad48: case 0xaee8: + s3->accel.setup_fifo_slot++; if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); else @@ -909,10 +1004,12 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xb548: case 0xb6e8: + s3->accel.setup_fifo_slot++; s3->accel.bkgd_mix = val; break; case 0xb948: case 0xbae8: + s3->accel.setup_fifo_slot++; s3->accel.frgd_mix = val; break; @@ -922,15 +1019,25 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xbd49: case 0xbee9: s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + switch (s3->accel.multifunc_cntl >> 12) { + case 0: + s3->accel.draw_fifo_slot++; + break; + case 0xa: + s3->accel.setup_fifo_slot++; + break; + } break; case 0xd148: case 0xd2e8: + s3->accel.setup_fifo_slot++; 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: + s3->accel.setup_fifo_slot++; 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 @@ -966,18 +1073,21 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; case 0xe948: case 0xeae8: + s3->accel.draw_fifo_slot++; 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.draw_fifo_slot++; 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: + s3->accel.setup_fifo_slot++; 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 @@ -1021,7 +1131,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) if (s3->accel.cmd & 0x100) { if (!(s3->accel.cmd & 0x600)) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } @@ -1036,59 +1149,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x200: /*Windows 95's built-in driver expects this to be loaded regardless of the byte swap bit (0xE2E9) in the 86c928*/ - if (s3->accel.cmd & 0x1000) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - } - } else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - } - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } } else { if (s3->chip == S3_86C928) s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } + else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } } break; case 0x400: if (svga->crtc[0x53] & 0x08) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else - 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; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } } } break; @@ -1108,59 +1213,51 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 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); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x200: /*Windows 95's built-in driver expects the upper 16 bits to be loaded instead of the whole 32-bit one, regardless of the byte swap bit (0xE2EB) in the 86c928*/ - if (s3->accel.cmd & 0x1000) { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); - } - } else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); - } - } else { - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else { - if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); - else - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - } } else { if (s3->chip == S3_86C928) - s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8)); - else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } + s3_accel_out_pixtrans_w(s3, s3->accel.pix_trans[2] | (s3->accel.pix_trans[3] << 8)); + else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } } break; case 0x400: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - 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); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x600: - if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip >= S3_TRIO64V) { + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } } } break; @@ -1168,23 +1265,46 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) } break; } + + if (s3_enable_fifo(s3) == 0) { + s3->accel.setup_fifo_slot = 0; + s3->accel.draw_fifo_slot = 0; + } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port == 0xb2e8) { - s3->accel.b2e8_pix = 1; + if (port != 0x9ee8 && port != 0x9d48) { + if (port == 0xb2e8) { + s3->accel.b2e8_pix = 1; + } else { + s3->accel.b2e8_pix = 0; + } + s3_accel_out_pixtrans_w(s3, val); } else { - s3->accel.b2e8_pix = 0; + s3->accel.short_stroke = val; + s3->accel.ssv_state = 1; + + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + if (s3->accel.cmd & 0x1000) { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + } else { + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); + s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); + } } - s3_accel_out_pixtrans_w(s3, val); } static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) -{ +{ s3_accel_out_pixtrans_l(s3, val); } @@ -1218,9 +1338,9 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ - + + case 0x811c: addr = 0x9ee8; break; + case 0x8120: case 0x8122: /*BKGD_COLOR*/ WRITE8(addr, s3->accel.bkgd_color, val); return; @@ -1348,16 +1468,22 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3_accel_out_fifo(s3, addr & 0xffff, val); } else { if (s3->accel.cmd & 0x100) { - if (!(s3->accel.cmd & 0x600)) { + if ((s3->accel.cmd & 0x600) == 0x200) { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, val, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } else - s3_accel_start(1, 1, 0xffffffff, val, s3); - } else if ((s3->accel.cmd & 0x600) == 0x200) { + s3_accel_start(2, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } else { if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, val, 0, s3); + if (((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); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } else - s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } } @@ -1382,12 +1508,19 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) case 0xff20: s3_accel_write_fifo(s3, addr, val); break; + case 0x811c: + s3_accel_out_fifo_w(s3, 0x9ee8, val); + break; } } } else { if (addr & 0x8000) { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); + if (addr == 0x811c) + s3_accel_out_fifo_w(s3, 0x9ee8, val); + else { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } } else { s3_accel_out_pixtrans_w(s3, val); } @@ -1602,59 +1735,6 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) } } -static void -fifo_thread(void *param) -{ - s3_t *s3 = (s3_t *)param; - - while (s3->thread_run) - { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); - - end_time = plat_timer_read(); - s3->blitter_time += end_time - start_time; - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } -} static void s3_vblank_start(svga_t *svga) @@ -1665,29 +1745,23 @@ s3_vblank_start(svga_t *svga) s3_update_irqs(s3); } -static void -s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) + +static uint32_t +s3_hwcursor_convert_addr(svga_t *svga) { - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); + if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x20) && (svga->crtc[0x45] & 0x10)) { + if ((svga->gdcreg[5] & 0x60) >= 0x40) + return ((svga->hwcursor_latch.addr & 0xfffff1ff) | ((svga->hwcursor_latch.addr & 0x200) << 2)) | 0x600; + else if ((svga->gdcreg[5] & 0x60) == 0x20) + return ((svga->hwcursor_latch.addr & 0xfffff0ff) | ((svga->hwcursor_latch.addr & 0x300) << 2)) | 0x300; + else + return svga->hwcursor_latch.addr; + } else + return svga->hwcursor_latch.addr; } + + static void s3_hwcursor_draw(svga_t *svga, int displine) { @@ -1698,6 +1772,8 @@ s3_hwcursor_draw(svga_t *svga, int displine) int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg, bg; + uint32_t real_addr; + uint32_t remapped_addr; switch (svga->bpp) { @@ -1705,9 +1781,11 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_15to32[s3->hwc_fg_col & 0xffff]; bg = video_15to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } } } break; @@ -1716,9 +1794,15 @@ s3_hwcursor_draw(svga_t *svga, int displine) fg = video_16to32[s3->hwc_fg_col & 0xffff]; bg = video_16to32[s3->hwc_bg_col & 0xffff]; if (s3->chip >= S3_86C928 && s3->chip <= S3_86C805) { - if (!(svga->crtc[0x45] & 0x04)) { - shift = 2; - width = 8; + if (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805) { + if (!(svga->crtc[0x45] & 0x04)) { + shift = 2; + width = 8; + } + } else if (s3->card_type == S3_MIROCRYSTAL10SD_805) { + if (!(svga->crtc[0x45] & 0x04)) { + offset <<= 1; + } } } break; @@ -1750,10 +1834,15 @@ s3_hwcursor_draw(svga_t *svga, int displine) if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; + real_addr = s3_hwcursor_convert_addr(svga); + for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_display_mask]; + remapped_addr = dword_remap(svga, real_addr); + + dat[0] = (svga->vram[remapped_addr & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 1) & s3->vram_mask]; + dat[1] = (svga->vram[(remapped_addr + 2) & s3->vram_mask] << 8) | svga->vram[(remapped_addr + 3) & s3->vram_mask]; + if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { @@ -1768,20 +1857,21 @@ s3_hwcursor_draw(svga_t *svga, int displine) } } else { /*Windows*/ - for (xx = 0; xx < width; xx++) { - if (offset >= svga->hwcursor_latch.x) { + for (xx = 0; xx < width; xx++) { + if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= shift; - dat[1] <<= shift; + } + + offset++; + dat[0] <<= shift; + dat[1] <<= shift; } } svga->hwcursor_latch.addr += 4; + real_addr = s3_hwcursor_convert_addr(svga); } if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -2081,7 +2171,7 @@ s3_io_remove_alt(s3_t *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, 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(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, 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); io_removehandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2115,7 +2205,7 @@ s3_io_remove(s3_t *s3) io_removehandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2144,8 +2234,9 @@ s3_io_set_alt(s3_t *s3) if (!s3->translate) return; - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 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); io_sethandler(0x4548, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2172,7 +2263,7 @@ s3_io_set_alt(s3_t *s3) 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(0x9d48, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, 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); io_sethandler(0xa948, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2202,8 +2293,9 @@ s3_io_set(s3_t *s3) io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - if ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) && (svga->seqregs[9] & 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); @@ -2230,7 +2322,7 @@ s3_io_set(s3_t *s3) 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(0x9ee8, 0x0002, s3_accel_in, s3_accel_in_w, NULL, s3_accel_out, s3_accel_out_w, NULL, s3); io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); @@ -2265,7 +2357,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) addr ^= 0x60; switch (addr) - { + { case 0x3c2: if ((s3->chip == S3_VISION964) || (s3->chip == S3_VISION968) || (s3->chip == S3_86C928)) { if (((val >> 2) & 3) != 3) @@ -2323,12 +2415,13 @@ s3_out(uint16_t addr, uint8_t val, void *p) else 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 && s3->card_type == S3_ELSAWIN2KPROX)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || + s3->card_type == S3_PHOENIX_VISION968))) ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); tvp3026_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) att49x_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip <= S3_86C924) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); @@ -2352,24 +2445,27 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if (s3->chip == S3_TRIO64V2 && svga->crtcreg >= 0x80) + if ((s3->chip == S3_TRIO64V2) && svga->crtcreg >= 0x80) return; old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) { case 0x31: s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + if (!svga->packed_chain4) + svga->force_dword_mode = val & 0x08; break; case 0x32: - if (svga->crtc[0x31] & 0x30) - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + if ((svga->crtc[0x31] & 0x30) && (svga->crtc[0x51] & 0x01) && (val & 0x40)) + svga->vram_display_mask = 0x3ffff; else svga->vram_display_mask = s3->vram_mask; break; case 0x40: - s3->enable_8514 = !!(svga->crtc[0x40] & 1); + s3->enable_8514 = (val & 0x01); break; case 0x50: @@ -2387,11 +2483,24 @@ s3_out(uint16_t addr, uint8_t val, void *p) } s3->bpp = (svga->crtc[0x50] >> 4) & 3; break; + + case 0x5c: + if ((val & 0xa0) == 0x80) + i2c_gpio_set(s3->i2c, !!(val & 0x40), !!(val & 0x10)); + if (s3->card_type == S3_PHOENIX_VISION868 || s3->card_type == S3_PHOENIX_VISION968) { + if ((val & 0x20) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x20; + } else if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968) { + if ((val & 0x80) && (!(svga->crtc[0x55] & 0x01) && !(svga->crtc[0x43] & 2))) + svga->dac_addr |= 0x02; + } + break; + case 0x69: if (s3->chip >= S3_VISION964) s3->ma_ext = val & 0x1f; break; - + case 0x35: s3->bank = (s3->bank & 0x70) | (val & 0xf); if (svga->chain4) @@ -2400,19 +2509,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; break; case 0x51: - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) + if (s3->chip == S3_86C801 || s3->chip == S3_86C805) { s3->bank = (s3->bank & 0x6f) | ((val & 0x4) << 2); - else + s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); + } else { s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + } if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; - if (s3->chip == S3_86C801 || s3->chip == S3_86C805) - s3->ma_ext = (s3->ma_ext & ~0x4) | ((val & 1) << 2); - else - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); break; + case 0x6a: if (s3->chip >= S3_VISION964) { s3->bank = val; @@ -2422,12 +2531,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = s3->bank << 14; } break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - + case 0x45: if (s3->chip == S3_VISION964 || s3->chip == S3_VISION968) break; @@ -2438,16 +2542,19 @@ s3_out(uint16_t addr, uint8_t val, void *p) 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; + if (svga->bpp == 32 && s3->chip != S3_VISION868) svga->hwcursor.x >>= 1; svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 63; - svga->hwcursor.yoff = svga->crtc[0x4f] & 63; + svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - if ((s3->chip >= S3_TRIO32) && svga->bpp == 32) + if ((s3->chip >= S3_TRIO32) && (s3->chip != S3_VISION868) && svga->bpp == 32) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) - svga->hwcursor.x >>= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) + else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 15 || svga->bpp == 16)) { + if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && svga->bpp == 16) + svga->hwcursor.x >>= 2; + else + svga->hwcursor.x >>= 1; + } else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && (svga->bpp == 24)) svga->hwcursor.x /= 3; break; @@ -2499,11 +2606,6 @@ 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_VISION968) || (s3->chip == S3_86C928)) { if (((svga->miscout >> 2) & 3) == 3) @@ -2514,7 +2616,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) case 0x43: if (s3->chip < S3_VISION964) { s3_io_remove_alt(s3); - s3->translate = !!(svga->crtc[0x43] & 0x10); + s3->translate = !!(val & 0x10); s3_io_set_alt(s3); } break; @@ -2581,8 +2683,14 @@ s3_in(uint16_t addr, void *p) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + temp = svga->seqregs[svga->seqaddr]; + /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not + get stuck in an infinite loop. */ + if ((s3->card_type == S3_PHOENIX_TRIO64VPLUS_ONBOARD) && (svga->seqaddr == 0x17)) + svga->seqregs[svga->seqaddr] ^= 0x01; + return temp; + } break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: @@ -2592,12 +2700,13 @@ s3_in(uint16_t addr, void *p) 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_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && s3->card_type == S3_ELSAWIN2KPROX)) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || + s3->card_type == S3_PHOENIX_VISION968))) return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); - else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V))) { + else if ((s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968))) { rs3 = !!(svga->crtc[0x55] & 0x02); return tvp3026_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805)) + } else if (((s3->chip == S3_86C801) || (s3->chip == S3_86C805)) && (s3->card_type != S3_MIROCRYSTAL10SD_805 && s3->card_type != S3_MIROCRYSTAL8S_805)) return att49x_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip <= S3_86C924) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); @@ -2636,7 +2745,7 @@ s3_in(uint16_t addr, void *p) /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ case 0x6b: - if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { + if (s3->chip != S3_TRIO64V2) { if (svga->crtc[0x53] & 0x08) { return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); } else { @@ -2646,10 +2755,10 @@ s3_in(uint16_t addr, void *p) return svga->crtc[0x6b]; break; case 0x6c: - if (s3->chip != S3_TRIO64V2 && s3->card_type != S3_MIROVIDEO40SV_968) { - if (svga->crtc[0x53] & 0x08) + if (s3->chip != S3_TRIO64V2) { + if (svga->crtc[0x53] & 0x08) { return 0x00; - else + } else return (svga->crtc[0x5a] & 0x80); } else return svga->crtc[0x6c]; @@ -2665,6 +2774,13 @@ static void s3_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->ma_latch |= (s3->ma_ext << 16); if (s3->chip >= S3_86C928) { svga->hdisp = svga->hdisp_old; @@ -2690,7 +2806,7 @@ static void s3_recalctimings(svga_t *svga) else bt48x_recalctimings(svga->ramdac, svga); } else if (s3->chip == S3_VISION968) { - if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_SPEA_MERCURY_P64V) + if (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968) tvp3026_recalctimings(svga->ramdac, svga); else ibm_rgb528_recalctimings(svga->ramdac, svga); @@ -2710,13 +2826,21 @@ static void s3_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if (((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) || (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) { - if (!(svga->crtc[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ - svga->force_dword_mode = 1; - } else - svga->force_dword_mode = 0; + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || + s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || + s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->bpp != 32) { + if (svga->crtc[0x31] & 2) /*This is needed if the pixel width gets set with delays*/ + s3->width = 2048; + } + } else if (s3->chip == S3_86C928) { + if (svga->bpp == 15) { + if (s3->width == 800) + s3->width = 1024; + } + } + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -2733,12 +2857,44 @@ static void s3_recalctimings(svga_t *svga) svga->hdisp *= 2; } - if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SD_864 || + s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp != 1408) svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864) { + if (s3->width == 2048) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + + case 768: + svga->hdisp = 1024; + break; + + case 864: + svga->hdisp = 1152; + break; + + case 1024: + if (svga->vtotal == 1066) + svga->hdisp = 1280; + break; + } + } + } } - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (svga->rowoffset == 256 && ((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04))) + if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL8S_805) { + if (svga->rowoffset == 256 && (((svga->crtc[0x51] & 0x30) == 0x00 && !(svga->crtc[0x43] & 0x04)))) svga->rowoffset >>= 1; } } @@ -2759,6 +2915,16 @@ static void s3_recalctimings(svga_t *svga) if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; } + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) { + if (svga->hdisp == (1408*2)) + svga->hdisp /= 2; + else + svga->hdisp = s3->width; + } + + if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805) + svga->hdisp = s3->width; break; case 16: svga->render = svga_render_16bpp_highres; @@ -2778,7 +2944,8 @@ static void s3_recalctimings(svga_t *svga) if (s3->width == 1280 || s3->width == 1600) svga->hdisp *= 2; } - if (s3->card_type == S3_MIROVIDEO40SV_968) { + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) { if (svga->hdisp == (1408*2)) svga->hdisp /= 2; else @@ -2796,7 +2963,8 @@ static void s3_recalctimings(svga_t *svga) else svga->hdisp = (svga->hdisp * 2) / 3; } else { - if (s3->card_type == S3_MIROVIDEO40SV_968) + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) svga->hdisp = s3->width; } break; @@ -2811,8 +2979,29 @@ static void s3_recalctimings(svga_t *svga) } if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V)) svga->hdisp *= 2; - if (s3->card_type == S3_MIROVIDEO40SV_968 || s3->card_type == S3_MIROCRYSTAL20SV_964) + if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || + s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || + s3->card_type == S3_SPEA_MERCURY_P64V) { svga->hdisp = s3->width; + if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { + if ((svga->crtc[0x31] & 2) && (svga->crtc[0x50] & 0xc1) != 0x00) { + switch (svga->dispend) { + case 400: + case 480: + svga->hdisp = 640; + break; + + case 576: + svga->hdisp = 768; + break; + + case 600: + svga->hdisp = 800; + break; + } + } + } + } break; } } else { @@ -2828,6 +3017,13 @@ static void s3_trio64v_recalctimings(svga_t *svga) s3_t *s3 = (s3_t *)svga->p; int clk_sel = (svga->miscout >> 2) & 3; + if (!svga->scrblank && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + if (svga->crtc[0x3a] & 0x10) /*256+ color register*/ + svga->gdcreg[5] |= 0x40; + } + } + svga->hdisp = svga->hdisp_old; if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -2853,12 +3049,6 @@ static void s3_trio64v_recalctimings(svga_t *svga) svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - if (svga->crtc[0x31] & 0x08) { - if (!(svga->crtc[0x17] & 0x40) && (svga->crtc[0x14] & 0x40)) /*Disable dword mode addressing when CRTC14 bit 6 is not enabled, regardless of the S3 dword mode bit.*/ - svga->force_dword_mode = 1; - } else - svga->force_dword_mode = 0; - switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -3018,14 +3208,17 @@ s3_updatemapping(s3_t *s3) svga->banked_mask = 0xffff; } } else { - if (s3->chip >= S3_TRIO64V) + if (s3->chip >= S3_TRIO64V) { s3->linear_base &= 0xfc000000; - else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) + svga->fb_only = 1; + } else if (s3->chip == S3_VISION968 || s3->chip == S3_VISION868) s3->linear_base &= 0xfe000000; mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); } } else { mem_mapping_disable(&s3->linear_mapping); + if (s3->chip >= S3_TRIO64V) + svga->fb_only = 0; } /* Memory mapped I/O. */ @@ -3040,7 +3233,7 @@ s3_updatemapping(s3_t *s3) mem_mapping_enable(&s3->mmio_mapping); } else mem_mapping_disable(&s3->mmio_mapping); - + /* New MMIO. */ if (svga->crtc[0x53] & 0x08) mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); @@ -3071,16 +3264,12 @@ 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; - if (port >= 0x8000) { - if (s3_enable_fifo(s3)) { - s3_queue(s3, port, val, FIFO_OUT_BYTE); - } else { - s3_accel_out_fifo(s3, port, val); - } + if (!s3->enable_8514) + return; + + s3_accel_out_fifo(s3, port, val); } else { @@ -3121,12 +3310,9 @@ s3_accel_out_w(uint16_t port, uint16_t val, void *p) s3_t *s3 = (s3_t *)p; if (!s3->enable_8514) - return; + return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_WORD); - else - s3_accel_out_fifo_w(s3, port, val); + s3_accel_out_fifo_w(s3, port, val); } static void @@ -3135,12 +3321,9 @@ s3_accel_out_l(uint16_t port, uint32_t val, void *p) s3_t *s3 = (s3_t *)p; if (!s3->enable_8514) - return; + return; - if (s3_enable_fifo(s3)) - s3_queue(s3, port, val, FIFO_OUT_DWORD); - else - s3_accel_out_fifo_l(s3, port, val); + s3_accel_out_fifo_l(s3, port, val); } static uint8_t @@ -3160,61 +3343,49 @@ s3_accel_in(uint16_t port, void *p) return s3->subsys_cntl; case 0x8148: case 0x82e8: - s3_wait_fifo_idle(s3); return s3->accel.cur_y & 0xff; case 0x8149: case 0x82e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + return s3->accel.cur_y >> 8; case 0x8548: case 0x86e8: - s3_wait_fifo_idle(s3); return s3->accel.cur_x & 0xff; case 0x8549: case 0x86e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + return s3->accel.cur_x >> 8; case 0x8948: case 0x8ae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp & 0xff; } break; case 0x8949: case 0x8ae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.desty_axstp >> 8; } break; case 0x8d48: case 0x8ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp & 0xff; } break; case 0x8d49: case 0x8ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.destx_distp >> 8; } break; case 0x9148: case 0x92e8: - s3_wait_fifo_idle(s3); return s3->accel.err_term & 0xff; case 0x9149: case 0x92e9: - s3_wait_fifo_idle(s3); return s3->accel.err_term >> 8; case 0x9548: case 0x96e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt & 0xff; } break; case 0x9549: case 0x96e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt >> 8; } break; @@ -3222,35 +3393,55 @@ s3_accel_in(uint16_t port, void *p) case 0x8118: case 0x9948: case 0x9ae8: temp = 0; /* FIFO empty */ - if (!s3->blitter_busy) - wake_fifo_thread(s3); - if (FIFO_FULL && (s3->chip >= S3_VISION964)) - temp = 0xff; /*FIFO full*/ - return temp; /*FIFO empty*/ + if (s3_enable_fifo(s3)) { + if (s3->accel.setup_fifo_slot) { + temp = s3->accel.setup_fifo; + s3->accel.setup_fifo = 0; + } else if (s3->accel.draw_fifo_slot) { + temp = s3->accel.draw_fifo; + s3->accel.draw_fifo = 0; + } + } + return temp; case 0x8119: case 0x9949: case 0x9ae9: - if (!s3->blitter_busy) - wake_fifo_thread(s3); temp = 0; - if ((s3->chip >= S3_86C928) && s3_enable_fifo(s3)) { - if (!FIFO_EMPTY || s3->force_busy) { + if (s3_enable_fifo(s3)) { + if ((s3->accel.setup_fifo_slot && s3->accel.draw_fifo_slot) || s3->force_busy) { temp |= 0x02; /*Hardware busy*/ } else { temp |= 0x04; /*FIFO empty*/ + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); } + s3->force_busy = 0; - if (s3->data_available && (s3->chip <= S3_86C805)) { + + if (s3->chip >= S3_VISION964) { + if (s3->accel.setup_fifo_slot > 8) { + temp |= s3->accel.setup_fifo2; + s3->accel.setup_fifo2 = 0; + } else if (s3->accel.draw_fifo_slot > 8) { + temp |= s3->accel.draw_fifo2; + s3->accel.draw_fifo2 = 0; + } + } + + if (s3->accel.setup_fifo_slot) + s3->accel.setup_fifo_slot--; + if (s3->accel.draw_fifo_slot) + s3->accel.draw_fifo_slot--; + + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } - if (FIFO_FULL && s3->chip >= S3_VISION964) - temp |= 0xf8; /*FIFO full*/ } else { if (s3->force_busy) { temp |= 0x02; /*Hardware busy*/ } s3->force_busy = 0; - if (s3->data_available && (s3->chip <= S3_86C805)) { + if (s3->data_available) { temp |= 0x01; /*Read Data available*/ s3->data_available = 0; } @@ -3259,126 +3450,101 @@ s3_accel_in(uint16_t port, void *p) case 0x9d48: case 0x9ee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke & 0xff; } break; case 0x9d49: case 0x9ee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.short_stroke >> 8; } break; case 0xa148: case 0xa2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color & 0xff; } break; case 0xa149: case 0xa2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 8; } break; case 0xa14a: case 0xa2ea: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 16; case 0xa14b: case 0xa2eb: - s3_wait_fifo_idle(s3); return s3->accel.bkgd_color >> 24; case 0xa548: case 0xa6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color & 0xff; } break; case 0xa549: case 0xa6e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 8; } break; case 0xa54a: case 0xa6ea: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 16; case 0xa54b: case 0xa6eb: - s3_wait_fifo_idle(s3); return s3->accel.frgd_color >> 24; case 0xa948: case 0xaae8: - if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); + if (s3->chip >= S3_86C928) { return s3->accel.wrt_mask & 0xff; } break; case 0xa949: case 0xaae9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 8; } break; case 0xa94a: case 0xaaea: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 16; case 0xa94b: case 0xaaeb: - s3_wait_fifo_idle(s3); return s3->accel.wrt_mask >> 24; case 0xad48: case 0xaee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.rd_mask & 0xff; } break; case 0xad49: case 0xaee9: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 8; case 0xad4a: case 0xaeea: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 16; case 0xad4b: case 0xaeeb: - s3_wait_fifo_idle(s3); return s3->accel.rd_mask >> 24; case 0xb148: case 0xb2e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp & 0xff; } break; case 0xb149: case 0xb2e9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 8; } break; case 0xb14a: case 0xb2ea: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 16; case 0xb14b: case 0xb2eb: - s3_wait_fifo_idle(s3); return s3->accel.color_cmp >> 24; case 0xb548: case 0xb6e8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.bkgd_mix; } break; case 0xb948: case 0xbae8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); return s3->accel.frgd_mix; } break; case 0xbd48: case 0xbee8: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; switch (temp) { @@ -3399,7 +3565,6 @@ s3_accel_in(uint16_t port, void *p) break; case 0xbd49: case 0xbee9: if (s3->chip >= S3_86C928) { - s3_wait_fifo_idle(s3); temp = s3->accel.multifunc[0xf] & 0xf; s3->accel.multifunc[0xf]++; switch (temp) @@ -3421,59 +3586,45 @@ s3_accel_in(uint16_t port, void *p) break; case 0xd148: case 0xd2e8: - s3_wait_fifo_idle(s3); return s3->accel.ropmix & 0xff; case 0xd149: case 0xd2e9: - s3_wait_fifo_idle(s3); return s3->accel.ropmix >> 8; case 0xe548: case 0xe6e8: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color & 0xff; case 0xe549: case 0xe6e9: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 8; case 0xe54a: case 0xe6ea: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 16; case 0xe54b: case 0xe6eb: - s3_wait_fifo_idle(s3); return s3->accel.pat_bg_color >> 24; case 0xe948: case 0xeae8: - s3_wait_fifo_idle(s3); return s3->accel.pat_y & 0xff; case 0xe949: case 0xeae9: - s3_wait_fifo_idle(s3); return s3->accel.pat_y >> 8; case 0xe94a: case 0xeaea: - s3_wait_fifo_idle(s3); return s3->accel.pat_x & 0xff; case 0xe94b: case 0xeaeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_x >> 8; case 0xed48: case 0xeee8: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color & 0xff; case 0xed49: case 0xeee9: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 8; case 0xed4a: case 0xeeea: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 16; case 0xed4b: case 0xeeeb: - s3_wait_fifo_idle(s3); return s3->accel.pat_fg_color >> 24; case 0xe148: case 0xe2e8: @@ -3484,9 +3635,12 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); } else - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -3509,15 +3663,32 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } else - s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } break; } } @@ -3537,13 +3708,19 @@ s3_accel_in(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 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); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 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); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); } else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); break; @@ -3573,25 +3750,40 @@ s3_accel_in_w(uint16_t port, void *p) if (!s3->enable_8514) return 0xffff; + + if (port != 0x9ee8 && port != 0x9d48) { + if (s3_cpu_dest(s3)) { + READ_PIXTRANS_WORD - if (s3_cpu_dest(s3)) { - READ_PIXTRANS_WORD - - switch (s3->accel.cmd & 0x600) { - case 0x000: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); - } else - s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); - break; - case 0x200: - if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); - } else - s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); - break; + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = (temp >> 8) | (temp << 8); + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + } else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); + break; + } } + } else { + temp = s3->accel.short_stroke; } + return temp; } @@ -3612,8 +3804,15 @@ s3_accel_in_l(uint16_t port, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(1, 1, 0xffffffff, temp, s3); s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); @@ -3621,8 +3820,15 @@ s3_accel_in_l(uint16_t port, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + temp = ((temp & 0xff00ff00) >> 8) | ((temp & 0x00ff00ff) << 8); + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, temp, s3); s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); @@ -3641,16 +3847,13 @@ 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) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); + s3_accel_write_fifo(s3, addr & 0x1ffff, val); else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); - } else - s3_accel_write_fifo(s3, addr & 0xffff, val); + s3_accel_write_fifo(s3, addr & 0xffff, val); } static void @@ -3659,16 +3862,13 @@ 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) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); + s3_accel_write_fifo_w(s3, addr & 0x1ffff, val); else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); - } else - s3_accel_write_fifo_w(s3, addr & 0xffff, val); + s3_accel_write_fifo_w(s3, addr & 0xffff, val); } static void @@ -3677,16 +3877,13 @@ 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) + if (!s3->enable_8514) return; - if (s3_enable_fifo(s3)) { if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); + s3_accel_write_fifo_l(s3, addr & 0x1ffff, val); else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); - } else - s3_accel_write_fifo_l(s3, addr & 0xffff, val); + s3_accel_write_fifo_l(s3, addr & 0xffff, val); } static uint8_t @@ -3696,9 +3893,8 @@ s3_accel_read(uint32_t addr, void *p) svga_t *svga = &s3->svga; uint8_t temp = 0x00; - if (!s3->enable_8514) { - return 0xff; - } + if (!s3->enable_8514) + return 0xff; if (svga->crtc[0x53] & 0x08) { if ((addr >= 0x08000) && (addr <= 0x0803f)) @@ -3734,15 +3930,21 @@ s3_accel_read(uint32_t addr, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); } else - s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 8) | (temp << 16) | (temp << 24), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); } else - s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 8) | (temp << 16) | (temp << 24), s3); break; } } @@ -3759,11 +3961,14 @@ s3_accel_read_w(uint32_t addr, void *p) uint16_t temp = 0x0000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffff; if (svga->crtc[0x53] & 0x08) { switch (addr & 0x1fffe) { + case 0x811c: + return s3->accel.short_stroke; + default: return s3_accel_read(addr, p) | s3_accel_read(addr + 1, p) << 8; @@ -3771,21 +3976,31 @@ s3_accel_read_w(uint32_t addr, void *p) return 0xffff; } else { if (addr & 0x8000) { - temp = s3_accel_read((addr & 0xfffe), p); - temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + if (addr == 0x811c) + temp = s3->accel.short_stroke; + else { + temp = s3_accel_read((addr & 0xfffe), p); + temp |= s3_accel_read((addr & 0xfffe) + 1, p) << 8; + } } else if (s3_cpu_dest(s3)) { READ_PIXTRANS_WORD switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(8, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(1, 1, 0xffffffff, temp | (temp << 16), s3); break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3_accel_start(16, 1, temp | (temp << 16), 0, s3); + else + s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); } else s3_accel_start(2, 1, 0xffffffff, temp | (temp << 16), s3); break; @@ -3805,7 +4020,7 @@ s3_accel_read_l(uint32_t addr, void *p) uint32_t temp = 0x00000000; uint16_t *vram_w = (uint16_t *)svga->vram; - if (!s3->enable_8514) + if (!s3->enable_8514) return 0xffffffff; if (svga->crtc[0x53] & 0x08) { @@ -3931,8 +4146,13 @@ s3_accel_read_l(uint32_t addr, void *p) switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(8, 1, temp, 0, s3); - s3_accel_start(8, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(8, 1, temp, 0, s3); + s3_accel_start(8, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(1, 1, 0xffffffff, temp, s3); + s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(1, 1, 0xffffffff, temp, s3); s3_accel_start(1, 1, 0xffffffff, temp >> 16, s3); @@ -3940,8 +4160,13 @@ s3_accel_read_l(uint32_t addr, void *p) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - s3_accel_start(16, 1, temp, 0, s3); - s3_accel_start(16, 1, temp >> 16, 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3_accel_start(16, 1, temp, 0, s3); + s3_accel_start(16, 1, temp >> 16, 0, s3); + } else { + s3_accel_start(2, 1, 0xffffffff, temp, s3); + s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); + } } else { s3_accel_start(2, 1, 0xffffffff, temp, s3); s3_accel_start(2, 1, 0xffffffff, temp >> 16, s3); @@ -3996,10 +4221,10 @@ 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 if (s3->bpp == 2) dat = svga->vram[(addr) & s3->vram_mask]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; +#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \ + else if (s3->bpp == 2) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ + else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)]; #define MIX_READ { \ switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ @@ -4304,23 +4529,23 @@ polygon_setup(s3_t *s3) #define WRITE(addr, dat) if (s3->bpp == 0) \ { \ - svga->vram[(addr) & s3->vram_mask] = dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ else if (s3->bpp == 1) \ { \ - vram_w[(addr) & (s3->vram_mask >> 1)] = dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ + vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \ + svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ } \ else if (s3->bpp == 2) \ { \ - svga->vram[(addr) & s3->vram_mask] = dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ + svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ else \ { \ - vram_l[(addr) & (s3->vram_mask >> 2)] = dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ + vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \ + svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ } @@ -4676,6 +4901,122 @@ s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3) } } +static void +s3_fifo_slots(s3_t *s3) +{ + switch (s3->accel.setup_fifo_slot) { + case 1: + s3->accel.setup_fifo |= 1; + break; + case 2: + s3->accel.setup_fifo |= 3; + break; + case 3: + s3->accel.setup_fifo |= 7; + break; + case 4: + s3->accel.setup_fifo |= 0x0f; + break; + case 5: + s3->accel.setup_fifo |= 0x1f; + break; + case 6: + s3->accel.setup_fifo |= 0x3f; + break; + case 7: + s3->accel.setup_fifo |= 0x7f; + break; + case 8: + s3->accel.setup_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x08; + break; + case 10: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x18; + break; + case 11: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x38; + break; + case 12: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0x78; + break; + case 13: + s3->accel.setup_fifo |= 0xff; + s3->accel.setup_fifo2 |= 0xf8; /* FIFO full */ + break; + } + + switch (s3->accel.draw_fifo_slot) { + case 1: + s3->accel.draw_fifo |= 1; + break; + case 2: + s3->accel.draw_fifo |= 3; + break; + case 3: + s3->accel.draw_fifo |= 7; + break; + case 4: + s3->accel.draw_fifo |= 0x0f; + break; + case 5: + s3->accel.draw_fifo |= 0x1f; + break; + case 6: + s3->accel.draw_fifo |= 0x3f; + break; + case 7: + s3->accel.draw_fifo |= 0x7f; + break; + case 8: + s3->accel.draw_fifo |= 0xff; /* FIFO full */ + break; + case 9: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x08; + break; + case 10: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x18; + break; + case 11: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x38; + break; + case 12: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0x78; + break; + case 13: + s3->accel.draw_fifo |= 0xff; + s3->accel.draw_fifo2 |= 0xf8; /* FIFO full */ + break; + } +} + +void +s3_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3, uint8_t ssv) +{ + if (!cpu_input) { + s3->accel.ssv_len = ssv & 0x0f; + s3->accel.ssv_dir = ssv & 0xe0; + s3->accel.ssv_draw = ssv & 0x10; + + s3_fifo_slots(s3); + + if (s3_cpu_src(s3)) { + return; /*Wait for data from CPU*/ + } + } + + s3_accel_start(count, cpu_input, mix_dat, cpu_dat, s3); +} + void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { @@ -4734,33 +5075,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 the mask source is the CPU, the color source can't be the same as the mask, or vice versa*/ - if (cpu_input) { - if (mix_dat & mix_mask) { - if ((s3->accel.cmd & 0x600) != 0x600) { - if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } - } else { - if (cmd == 3) { - if (((s3->accel.frgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } else { - if ((s3->accel.cmd & 0x600) != 0x600) { - if (((s3->accel.bkgd_mix & 0x60) == 0x40) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)) { - cpu_dat = mix_dat; - count >>= 3; - } - } - } - } - } - + if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { if ((s3->bpp == 3) && count == 2) { if (s3->accel.dat_count) { @@ -4783,6 +5098,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else if (s3->bpp == 1) rd_mask &= 0xffff; + if (s3->bpp == 0) compare &= 0xff; + if (s3->bpp == 1) compare &= 0xffff; + switch (s3->accel.cmd & 0x600) { case 0x000: mix_mask = 0x80; break; @@ -4790,10 +5108,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0x400: mix_mask = 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; - if (s3->bpp == 1) compare &= 0xffff; - + /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ @@ -4802,40 +5117,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0: /*NOP (Short Stroke Vectors)*/ if (s3->accel.ssv_state == 0) break; - - if (!cpu_input) { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - - if (s3->accel.cmd & 0x1000) { - s3->accel.ssv_len1 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir1 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw1 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len2 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir2 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw2 = s3->accel.short_stroke & 0x10; - } else { - s3->accel.ssv_len2 = (s3->accel.short_stroke >> 8) & 0x0f; - s3->accel.ssv_dir2 = (s3->accel.short_stroke >> 8) & 0xe0; - s3->accel.ssv_draw2 = (s3->accel.short_stroke >> 8) & 0x10; - s3->accel.ssv_len1 = s3->accel.short_stroke & 0x0f; - s3->accel.ssv_dir1 = s3->accel.short_stroke & 0xe0; - s3->accel.ssv_draw1 = s3->accel.short_stroke & 0x10; - } - - if (s3_cpu_src(s3)) { - return; /*Wait for data from CPU*/ - } - } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.ssv_len1 >= 0) + { + while (count-- && s3->accel.ssv_len >= 0) { 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) @@ -4856,7 +5144,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ MIX - if (s3->accel.ssv_draw1) { + if (s3->accel.ssv_draw) { WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); } } @@ -4866,10 +5154,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; - if (!s3->accel.ssv_len1) + if (!s3->accel.ssv_len) break; - switch (s3->accel.ssv_dir1 & 0xe0) + switch (s3->accel.ssv_dir & 0xe0) { case 0x00: s3->accel.cx++; break; case 0x20: s3->accel.cx++; s3->accel.cy--; break; @@ -4880,56 +5168,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ case 0xc0: s3->accel.cy++; break; case 0xe0: s3->accel.cx++; s3->accel.cy++; break; } - s3->accel.ssv_len1--; + + s3->accel.ssv_len--; } - - while (count-- && s3->accel.ssv_len2 >= 0) - { - 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 ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - if (s3->accel.ssv_draw2) { - WRITE((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.ssv_len2) - break; - - switch (s3->accel.ssv_dir2 & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.ssv_len2--; - } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; } @@ -4944,11 +5186,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy = s3->accel.maj_axis_pcnt; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { return; /*Wait for data from CPU*/ } } - + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -5122,9 +5366,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy |= ~0xfff; } } - + s3->accel.dest = dstbase + s3->accel.cy * s3->width; + s3_fifo_slots(s3); + if (s3_cpu_src(s3)) { s3->data_available = 0; return; /*Wait for data from CPU*/ @@ -5247,6 +5493,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -5356,9 +5604,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } } - + s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -5368,6 +5618,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) @@ -5395,7 +5646,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - + s3->accel.cy++; s3->accel.dy++; @@ -5451,6 +5702,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat <<= 1; mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; else cpu_dat >>= 16; @@ -5476,7 +5728,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ { s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } + } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; @@ -5496,11 +5748,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy--; - if (cpu_input) + if (cpu_input) { return; + } - if (s3->accel.sy < 0) + if (s3->accel.sy < 0) { return; + } } } } @@ -5521,7 +5775,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.cur_x_bit12) s3->accel.cx |= ~0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; - + /*Align source with destination*/ s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -5530,6 +5784,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.dy & 7; s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) { @@ -5621,9 +5877,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sy--; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) + if (cpu_input) { return; + } + if (s3->accel.sy < 0) { + return; + } } } break; @@ -5649,6 +5908,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy = s3->accel.cur_y; if (s3->accel.cur_y_bit12) s3->accel.cy |= ~0xfff; + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -5741,6 +6002,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ polygon_setup(s3); + s3_fifo_slots(s3); + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ end_y1 = s3->accel.desty_axstp; @@ -5750,6 +6013,7 @@ 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; + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) { int y = s3->accel.poly_cy; @@ -5850,7 +6114,9 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ 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); + s3->accel.pattern = (s3->accel.py * s3->width); + + s3_fifo_slots(s3); } if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ @@ -6043,7 +6309,7 @@ s3_pci_write(int func, int addr, uint8_t val, void *p) { s3_t *s3 = (s3_t *)p; svga_t *svga = &s3->svga; - + switch (addr) { case 0x00: case 0x01: case 0x02: case 0x03: @@ -6122,7 +6388,7 @@ static int vram_sizes[] = 0, 0, /*4 MB*/ 0, - 0, + 0, /*6 MB*/ 0, 3 /*8 MB*/ }; @@ -6162,6 +6428,11 @@ static void *s3_init(const device_t *info) chip = S3_86C805; video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); break; + case S3_MIROCRYSTAL8S_805: + bios_fn = ROM_MIROCRYSTAL8S_805; + chip = S3_86C805; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c805); + break; case S3_MIROCRYSTAL10SD_805: bios_fn = ROM_MIROCRYSTAL10SD_805; chip = S3_86C805; @@ -6185,6 +6456,11 @@ static void *s3_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_86c801); break; + case S3_MIROCRYSTAL20SD_864: + bios_fn = ROM_MIROCRYSTAL20SD_864_VLB; + chip = S3_VISION864; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + break; case S3_PARADISE_BAHAMAS64: bios_fn = ROM_PARADISE_BAHAMAS64; chip = S3_VISION864; @@ -6221,14 +6497,19 @@ static void *s3_init(const device_t *info) chip = S3_VISION964; if (info->flags & DEVICE_PCI) { bios_fn = ROM_MIROCRYSTAL20SV_964_PCI; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_pci); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_pci); } else { bios_fn = ROM_MIROCRYSTAL20SV_964_VLB; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision864_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); } break; - case S3_MIROVIDEO40SV_968: - bios_fn = ROM_MIROVIDEO40SV_968; + case S3_MIROVIDEO40SV_ERGO_968: + bios_fn = ROM_MIROVIDEO40SV_ERGO_968_PCI; + chip = S3_VISION968; + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + break; + case S3_PHOENIX_VISION968: + bios_fn = ROM_PHOENIX_VISION968; chip = S3_VISION968; if (info->flags & DEVICE_PCI) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); @@ -6331,11 +6612,7 @@ static void *s3_init(const device_t *info) memset(s3, 0, sizeof(s3_t)); - if (info->local == S3_MIROCRYSTAL10SD_805 || info->local == S3_SPEA_MIRAGE_86C801 || - info->local == S3_SPEA_MIRAGE_86C805) - vram = 1; - else - vram = device_get_config_int("memory"); + vram = device_get_config_int("memory"); if (vram) vram_size = vram << 20; @@ -6401,9 +6678,10 @@ 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 && info->local == S3_ELSAWIN2KPROX)) + else if ((chip == S3_VISION964 && info->local == S3_ELSAWIN2KPROX_964) || (chip == S3_VISION968 && (info->local == S3_ELSAWIN2KPROX || + info->local == S3_PHOENIX_VISION968))) svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; - else if (chip == S3_VISION968 && (info->local == S3_MIROVIDEO40SV_968 || info->local == S3_SPEA_MERCURY_P64V)) + else if (chip == S3_VISION968 && (info->local == S3_SPEA_MERCURY_P64V || info->local == S3_MIROVIDEO40SV_ERGO_968)) svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; if (chip >= S3_VISION964) { @@ -6498,6 +6776,7 @@ static void *s3_init(const device_t *info) svga->getclock = ics2494_getclock; break; + case S3_MIROCRYSTAL8S_805: case S3_MIROCRYSTAL10SD_805: svga->decode_mask = (2 << 20) - 1; stepping = 0xa0; /*86C801/86C805*/ @@ -6558,6 +6837,7 @@ static void *s3_init(const device_t *info) case S3_PARADISE_BAHAMAS64: case S3_PHOENIX_VISION864: + case S3_MIROCRYSTAL20SD_864: svga->decode_mask = (8 << 20) - 1; if (info->local == S3_PARADISE_BAHAMAS64) stepping = 0xc0; /*Vision864*/ @@ -6590,11 +6870,11 @@ static void *s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; break; - case S3_ELSAWIN2KPROX: - case S3_MIROVIDEO40SV_968: case S3_SPEA_MERCURY_P64V: + case S3_MIROVIDEO40SV_ERGO_968: + case S3_PHOENIX_VISION968: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ s3->id_ext = s3->id_ext_pci = 0xf0; @@ -6610,8 +6890,8 @@ static void *s3_init(const device_t *info) svga->crtc[0x59] = 0x00; svga->crtc[0x5a] = 0x0a; } - - if (info->local == S3_ELSAWIN2KPROX) + + if (info->local == S3_ELSAWIN2KPROX || info->local == S3_PHOENIX_VISION968) svga->ramdac = device_add(&ibm_rgb528_ramdac_device); else svga->ramdac = device_add(&tvp3026_ramdac_device); @@ -6703,18 +6983,14 @@ static void *s3_init(const device_t *info) return NULL; } + if (s3->chip >= S3_TRIO64V) + svga->packed_chain4 = 1; + if (s3->pci) s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); s3->i2c = i2c_gpio_init("ddc_s3"); s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); - - svga->packed_chain4 = 1; - - s3->wake_fifo_thread = thread_create_event(); - s3->fifo_not_full_event = thread_create_event(); - s3->thread_run = 1; - s3->fifo_thread = thread_create(fifo_thread, s3); return s3; } @@ -6749,6 +7025,11 @@ static int s3_phoenix_86c80x_available(void) return rom_present(ROM_PHOENIX_86C80X); } +static int s3_mirocrystal_8s_805_available(void) +{ + return rom_present(ROM_MIROCRYSTAL8S_805); +} + static int s3_mirocrystal_10sd_805_available(void) { return rom_present(ROM_MIROCRYSTAL10SD_805); @@ -6789,9 +7070,19 @@ static int s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } -static int s3_mirovideo_40sv_968_available(void) +static int s3_mirovideo_40sv_ergo_968_pci_available(void) { - return rom_present(ROM_MIROVIDEO40SV_968); + return rom_present(ROM_MIROVIDEO40SV_ERGO_968_PCI); +} + +static int s3_phoenix_vision968_available(void) +{ + return rom_present(ROM_PHOENIX_VISION968); +} + +static int s3_mirocrystal_20sd_864_vlb_available(void) +{ + return rom_present(ROM_MIROCRYSTAL20SD_864_VLB); } static int s3_spea_mercury_p64v_pci_available(void) @@ -6855,12 +7146,6 @@ static void s3_close(void *p) svga_close(&s3->svga); - s3->thread_run = 0; - thread_set_event(s3->wake_fifo_thread); - thread_wait(s3->fifo_thread, -1); - thread_destroy_event(s3->wake_fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); - ddc_close(s3->ddc); i2c_gpio_close(s3->i2c); @@ -7053,7 +7338,7 @@ const device_t s3_spea_mirage_86c801_isa_device = { s3_spea_mirage_86c801_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; const device_t s3_spea_mirage_86c805_vlb_device = @@ -7067,12 +7352,27 @@ const device_t s3_spea_mirage_86c805_vlb_device = { s3_spea_mirage_86c805_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; +const device_t s3_mirocrystal_8s_805_vlb_device = +{ + "S3 86c805 VLB (MiroCRYSTAL 8S)", + DEVICE_VLB, + S3_MIROCRYSTAL8S_805, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_8s_805_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + + const device_t s3_mirocrystal_10sd_805_vlb_device = { - "S3 86c805 VLB (MiroCrystal 10SD)", + "S3 86c805 VLB (MiroCRYSTAL 10SD)", DEVICE_VLB, S3_MIROCRYSTAL10SD_805, s3_init, @@ -7081,7 +7381,7 @@ const device_t s3_mirocrystal_10sd_805_vlb_device = { s3_mirocrystal_10sd_805_available }, s3_speed_changed, s3_force_redraw, - NULL + s3_9fx_config }; const device_t s3_phoenix_86c801_isa_device = @@ -7140,6 +7440,20 @@ const device_t s3_metheus_86c928_vlb_device = s3_standard_config }; +const device_t s3_mirocrystal_20sd_864_vlb_device = +{ + "S3 Vision864 VLB (MiroCRYSTAL 20SD)", + DEVICE_VLB, + S3_MIROCRYSTAL20SD_864, + s3_init, + s3_close, + NULL, + { s3_mirocrystal_20sd_864_vlb_available }, + s3_speed_changed, + s3_force_redraw, + s3_9fx_config +}; + const device_t s3_bahamas64_vlb_device = { "S3 Vision864 VLB (Paradise Bahamas 64)", @@ -7225,29 +7539,43 @@ const device_t s3_diamond_stealth64_964_pci_device = s3_standard_config }; -const device_t s3_mirovideo_40sv_968_vlb_device = +const device_t s3_phoenix_vision968_pci_device = { - "S3 Vision968 VLB (MiroVIDEO 40SV)", - DEVICE_VLB, - S3_MIROVIDEO40SV_968, + "S3 Vision968 PCI (Phoenix)", + DEVICE_PCI, + S3_PHOENIX_VISION968, s3_init, s3_close, NULL, - { s3_mirovideo_40sv_968_available }, + { s3_phoenix_vision968_available }, s3_speed_changed, s3_force_redraw, s3_standard_config }; -const device_t s3_mirovideo_40sv_968_pci_device = +const device_t s3_phoenix_vision968_vlb_device = { - "S3 Vision968 PCI (MiroVIDEO 40SV)", - DEVICE_PCI, - S3_MIROVIDEO40SV_968, + "S3 Vision968 VLB (Phoenix)", + DEVICE_VLB, + S3_PHOENIX_VISION968, s3_init, s3_close, NULL, - { s3_mirovideo_40sv_968_available }, + { s3_phoenix_vision968_available }, + s3_speed_changed, + s3_force_redraw, + s3_standard_config +}; + +const device_t s3_mirovideo_40sv_ergo_968_pci_device = +{ + "S3 Vision968 PCI (MiroVIDEO 40SV Ergo)", + DEVICE_PCI, + S3_MIROVIDEO40SV_ERGO_968, + s3_init, + s3_close, + NULL, + { s3_mirovideo_40sv_ergo_968_pci_available }, s3_speed_changed, s3_force_redraw, s3_standard_config diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 88365b427..008232bc4 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -758,7 +758,7 @@ sigma_poll(void *p) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, sigma->firstline - 4, 0, (sigma->lastline - sigma->firstline) + 8, xsize, (sigma->lastline - sigma->firstline) + 8); + video_blit_memtoscreen_8(0, sigma->firstline - 4, xsize, (sigma->lastline - sigma->firstline) + 8); frames++; video_res_x = xsize - 16; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 07f6f3823..b38353701 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -41,7 +41,7 @@ #include <86box/vid_svga_render.h> -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +void svga_doblit(int wx, int wy, svga_t *svga); extern int cyc_total; extern uint8_t edatlookup[4][4]; @@ -823,10 +823,10 @@ svga_poll(void *p) if (!svga->override) { if (svga->vertical_linedbl) { wy = (svga->lastline - svga->firstline) << 1; - svga_doblit(svga->firstline_draw << 1, (svga->lastline_draw + 1) << 1, wx, wy, svga); + svga_doblit(wx, wy, svga); } else { wy = svga->lastline - svga->firstline; - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + svga_doblit(wx, wy, svga); } } @@ -1342,7 +1342,7 @@ svga_read_linear(uint32_t addr, void *p) void -svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) +svga_doblit(int wx, int wy, svga_t *svga) { int y_add, x_add, y_start, x_start, bottom; uint32_t *p; @@ -1361,15 +1361,8 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) bottom <<= 1; } - if ((wx <= 0) || (wy <= 0)) { - video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); + if ((wx <= 0) || (wy <= 0)) return; - } - - if (y1 > y2) { - video_blit_memtoscreen(x_start, y_start, 0, 0, xsize + x_add, ysize + y_add); - return; - } if (svga->vertical_linedbl) svga->y_add <<= 1; @@ -1423,7 +1416,7 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) } } - video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(x_start, y_start, xsize + x_add, ysize + y_add); if (svga->vertical_linedbl) svga->vertical_linedbl >>= 1; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a26727e25..aa40e3079 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -145,7 +145,8 @@ video_cards[] = { { "n9_9fx_pci", &s3_9fx_pci_device }, { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, { "elsawin2kprox_pci", &s3_elsa_winner2000_pro_x_pci_device }, - { "mirovideo40sv_pci", &s3_mirovideo_40sv_968_pci_device }, + { "mirovideo40sv_pci", &s3_mirovideo_40sv_ergo_968_pci_device }, + { "px_vision968_pci", &s3_phoenix_vision968_pci_device }, { "spea_mercury64p_pci", &s3_spea_mercury_p64v_pci_device }, { "px_vision868_pci", &s3_phoenix_vision868_pci_device }, { "px_trio64vplus_pci", &s3_phoenix_trio64vplus_pci_device }, @@ -184,11 +185,13 @@ video_cards[] = { { "stealth3d_2000_vlb", &s3_virge_vlb_device }, { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, { "metheus928_vlb", &s3_metheus_86c928_vlb_device }, + { "mirocrystal8s_vlb", &s3_mirocrystal_8s_805_vlb_device }, { "mirocrystal10sd_vlb", &s3_mirocrystal_10sd_805_vlb_device }, { "px_86c805_vlb", &s3_phoenix_86c805_vlb_device }, { "px_s3_v7_805_vlb", &s3_spea_mirage_86c805_vlb_device }, { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device }, { "mirocrystal20sv_vlb", &s3_mirocrystal_20sv_964_vlb_device }, + { "mirocrystal20sd_vlb", &s3_mirocrystal_20sd_864_vlb_device }, { "bahamas64_vlb", &s3_bahamas64_vlb_device }, { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device }, { "stealthse_vlb", &s3_diamond_stealth_se_vlb_device }, @@ -197,6 +200,7 @@ video_cards[] = { { "n9_9fx_vlb", &s3_9fx_vlb_device }, { "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, { "spea_miragep64_vlb", &s3_spea_mirage_p64_vlb_device }, + { "px_vision968_vlb", &s3_phoenix_vision968_vlb_device }, { "px_vision868_vlb", &s3_phoenix_vision868_vlb_device }, { "ht216_32", &ht216_32_standalone_device }, { "virge325_vlb", &s3_virge_325_vlb_device }, diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 23805cb41..c77b2368e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -2407,7 +2407,7 @@ static uint8_t banshee_pci_read(int func, int addr, void *p) case 0x00: ret = 0x1a; break; /*3DFX*/ case 0x01: ret = 0x12; break; - case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : ((banshee->type == TYPE_VELOCITY100) ? 0x04 : 0x05); break; + case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break; case 0x03: ret = 0x00; break; case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break; @@ -2858,7 +2858,14 @@ static void *banshee_init_common(const device_t *info, char *fn, int has_sgram, banshee->pci_regs[0x2e] = 0x3a; banshee->pci_regs[0x2f] = 0x00; break; - } + + case TYPE_VELOCITY100: + banshee->pci_regs[0x2c] = 0x1a; + banshee->pci_regs[0x2d] = 0x12; + banshee->pci_regs[0x2e] = 0x4b; + banshee->pci_regs[0x2f] = 0x00; + break; + } video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee); diff --git a/src/video/vid_voodoo_display.c b/src/video/vid_voodoo_display.c index bfee8554c..a52249bee 100644 --- a/src/video/vid_voodoo_display.c +++ b/src/video/vid_voodoo_display.c @@ -655,7 +655,7 @@ skip_draw: thread_release_mutex(voodoo->force_blit_mutex); if (voodoo->dirty_line_high > voodoo->dirty_line_low || force_blit) - svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); + svga_doblit(voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); if (voodoo->clutData_dirty) { voodoo->clutData_dirty = 0; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index 0affbd58e..57faf5fdc 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -870,7 +870,7 @@ void wy700_poll(void *p) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, xsize, ysize); frames++; /* Fixed 1280x800 resolution */ diff --git a/src/video/video.c b/src/video/video.c index 008228a00..1258b1824 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -74,7 +74,6 @@ volatile int screenshots = 0; bitmap_t *buffer32 = NULL; -bitmap_t *render_buffer = NULL; uint8_t fontdat[2048][8]; /* IBM CGA font */ uint8_t fontdatm[2048][16]; /* IBM MDA font */ uint8_t fontdatw[512][32]; /* Wyse700 font */ @@ -245,7 +244,7 @@ const uint32_t shade[5][256] = static struct { - int x, y, y1, y2, w, h; + int x, y, w, h; int busy; int buffer_in_use; @@ -256,7 +255,7 @@ static struct { } blit_data; -static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); +static void (*blit_func)(int x, int y, int w, int h); #ifdef ENABLE_VIDEO_LOG @@ -280,7 +279,7 @@ video_log(const char *fmt, ...) void -video_setblit(void(*blit)(int,int,int,int,int,int)) +video_setblit(void(*blit)(int,int,int,int)) { blit_func = blit; } @@ -318,7 +317,7 @@ static png_infop info_ptr; static void -video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, int w, int h) +video_take_screenshot(const char *fn) { int i, x, y; png_bytep *b_rgb = NULL; @@ -350,25 +349,28 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in png_init_io(png_ptr, fp); - png_set_IHDR(png_ptr, info_ptr, w, h, + png_set_IHDR(png_ptr, info_ptr, blit_data.w, blit_data.h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * h); + b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data.h); if (b_rgb == NULL) { video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory"); fclose(fp); return; } - for (y = 0; y < h; ++y) { + for (y = 0; y < blit_data.h; ++y) { b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); - for (x = 0; x < w; ++x) { - temp = render_buffer->dat[(y * w) + x]; - - b_rgb[y][(x) * 3 + 0] = (temp >> 16) & 0xff; - b_rgb[y][(x) * 3 + 1] = (temp >> 8) & 0xff; - b_rgb[y][(x) * 3 + 2] = temp & 0xff; + for (x = 0; x < blit_data.w; ++x) { + if (buffer32 == NULL) + memset(&(b_rgb[y][x * 3]), 0x00, 3); + else { + temp = buffer32->line[blit_data.y + y][blit_data.x + x]; + b_rgb[y][x * 3] = (temp >> 16) & 0xff; + b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff; + b_rgb[y][(x * 3) + 2] = temp & 0xff; + } } } @@ -379,7 +381,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in png_write_end(png_ptr, NULL); /* cleanup heap allocation */ - for (i = 0; i < h; i++) + for (i = 0; i < blit_data.h; i++) if (b_rgb[i]) free(b_rgb[i]); if (b_rgb) free(b_rgb); @@ -389,7 +391,7 @@ video_take_screenshot(const char *fn, int startx, int starty, int y1, int y2, in static void -video_screenshot(int x, int y, int y1, int y2, int w, int h) +video_screenshot(void) { char path[1024], fn[128]; @@ -408,7 +410,7 @@ video_screenshot(int x, int y, int y1, int y2, int w, int h) video_log("taking screenshot to: %s\n", path); - video_take_screenshot((const char *) path, x, y, y1, y2, w, h); + video_take_screenshot((const char *) path); png_destroy_write_struct(&png_ptr, &info_ptr); } @@ -418,10 +420,12 @@ video_transform_copy(uint32_t *dst, uint32_t *src, int len) { int i; - for (i = 0; i < len; i++) { - *dst = video_color_transform(*src); - dst++; - src++; + if ((dst != NULL) && (src != NULL)) { + for (i = 0; i < len; i++) { + *dst = video_color_transform(*src); + dst++; + src++; + } } } @@ -436,28 +440,22 @@ void blit_thread(void *param) thread_reset_event(blit_data.wake_blit_thread); MTR_BEGIN("video", "blit_thread"); - if (blit_data.y2 > 0) { - for (yy = blit_data.y1; yy < blit_data.y2; yy++) { + if ((video_grayscale || invert_display) && (blit_data.h > 0)) { + for (yy = 0; yy < blit_data.h; yy++) { if (((blit_data.y + yy) >= 0) && ((blit_data.y + yy) < buffer32->h)) { - if (video_grayscale || invert_display) - video_transform_copy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); - else - memcpy(&(render_buffer->dat)[yy * blit_data.w], &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w << 2); + video_transform_copy(&(buffer32->line[blit_data.y + yy][blit_data.x]), &(buffer32->line[blit_data.y + yy][blit_data.x]), blit_data.w); } } } if (screenshots) { - if (render_buffer != NULL) - video_screenshot(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); + video_screenshot(); screenshots--; video_log("screenshot taken, %i left\n", screenshots); } if (blit_func) - blit_func(blit_data.x, blit_data.y, - blit_data.y1, blit_data.y2, - blit_data.w, blit_data.h); + blit_func(blit_data.x, blit_data.y, blit_data.w, blit_data.h); blit_data.busy = 0; @@ -468,7 +466,7 @@ void blit_thread(void *param) void -video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) +video_blit_memtoscreen(int x, int y, int w, int h) { MTR_BEGIN("video", "video_blit_memtoscreen"); @@ -481,8 +479,6 @@ video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) blit_data.buffer_in_use = 1; blit_data.x = x; blit_data.y = y; - blit_data.y1 = y1; - blit_data.y2 = y2; blit_data.w = w; blit_data.h = h; @@ -546,7 +542,7 @@ video_blend(int x, int y) void -video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) +video_blit_memtoscreen_8(int x, int y, int w, int h) { int yy, xx; @@ -563,7 +559,7 @@ video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) } } - video_blit_memtoscreen(x, y, y1, y2, w, h); + video_blit_memtoscreen(x, y, w, h); } @@ -833,7 +829,6 @@ video_init(void) /* Account for overscan. */ buffer32 = create_bitmap(2048 + 64, 2048 + 64); - render_buffer = create_bitmap(2048 + 64, 2048 + 64); for (c = 0; c < 64; c++) { cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; @@ -902,7 +897,6 @@ video_close(void) free(video_8togs); free(video_6to8); - destroy_bitmap(render_buffer); destroy_bitmap(buffer32); if (fontdatksc5601) { diff --git a/src/vnc.c b/src/vnc.c index 09c00831f..f2f4655b0 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -167,16 +167,19 @@ vnc_display(rfbClientPtr cl) static void -vnc_blit(int x, int y, int y1, int y2, int w, int h) +vnc_blit(int x, int y, int w, int h) { uint32_t *p; int yy; - for (yy=y1; yyframeBuffer)[yy*VNC_MAX_X]); if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(render_buffer->dat[yy * w]), w*4); + memcpy(p, &(buffer32->line[yy]), w*sizeof(uint32_t)); } video_blit_complete(); diff --git a/src/win/86Box.manifest b/src/win/86Box.manifest index 454e1df65..045e12dbf 100644 --- a/src/win/86Box.manifest +++ b/src/win/86Box.manifest @@ -32,4 +32,18 @@ UTF-8 + + + + + + + + + + + + + + diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 6102cde68..527f64f51 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -15,7 +15,7 @@ enable_language(RC) -add_library(plat OBJECT win.c win_dynld.c win_thread.c win_cdrom.c +add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c win_crashdump.c win_midi.c win_mouse.c) add_library(ui OBJECT win_ui.c win_stbar.c win_sdl.c win_dialog.c win_about.c @@ -58,5 +58,9 @@ if(OPENGL) target_sources(ui PRIVATE glad.c win_opengl.c win_opengl_glslp.c) endif() +if(NOT PTHREAD) + target_sources(plat PRIVATE win_thread.c) +endif() + target_link_libraries(86Box advapi32 comctl32 comdlg32 gdi32 shell32 iphlpapi dxguid imm32 hid setupapi uxtheme version winmm psapi) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index e050dab7c..7be4baa8f 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -26,6 +26,10 @@ ifndef DEV_BUILD DEV_BUILD := n endif +ifneq ($(PTHREAD), n) + PTHREAD := y +endif + ifeq ($(DEV_BUILD), y) ifndef DEBUG DEBUG := y @@ -607,10 +611,17 @@ CXXFLAGS := $(CFLAGS) ######################################################################### # Create the (final) list of objects to build. # ######################################################################### +ifeq ($(PTHREAD), y) +MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ + nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ + usb.o device.o nvr.o nvr_at.o nvr_ps2.o thread.o \ + $(VNCOBJ) +else MAINOBJ := 86box.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ nmi.o pic.o pit.o port_92.o ppi.o pci.o mca.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o \ $(VNCOBJ) +endif MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o @@ -620,7 +631,7 @@ CPUOBJ := $(DYNARECOBJ) \ 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ x86seg.o x87.o x87_timings.o -CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ +CHIPSETOBJ := 82c100.o acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o et6000.o headland.o intel_82335.o cs4031.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ gc100.o \ @@ -635,7 +646,7 @@ MCHOBJ := machine.o machine_table.o \ m_xt_xi8088.o m_xt_zenith.o \ m_pcjr.o \ m_amstrad.o m_europc.o \ - m_xt_olivetti.o m_tandy.o \ + m_xt_olivetti.o m_tandy.o m_v86p.o \ m_at.o m_at_commodore.o \ m_at_t3100e.o m_at_t3100e_vid.o \ m_ps1.o m_ps1_hdc.o \ @@ -773,6 +784,7 @@ VIDOBJ := video.o \ vid_paradise.o \ vid_rtg310x.o \ vid_ti_cf62011.o \ + vid_f82c425.o \ vid_tvga.o \ vid_tgui9440.o vid_tkd8001_ramdac.o \ vid_att20c49x_ramdac.o \ @@ -790,11 +802,19 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \ vid_voodoo_render.o vid_voodoo_setup.o \ vid_voodoo_texture.o +ifeq ($(PTHREAD), y) +PLATOBJ := win.o \ + win_dynld.o \ + win_cdrom.o win_keyboard.o \ + win_crashdump.o win_midi.o \ + win_mouse.o +else PLATOBJ := win.o \ win_dynld.o win_thread.o \ win_cdrom.o win_keyboard.o \ win_crashdump.o win_midi.o \ win_mouse.o +endif ifeq ($(DINPUT), y) PLATOBJ += win_joystick.o @@ -820,7 +840,11 @@ endif ifneq ($(WX), n) LIBS += $(WX_LIBS) -lm endif +ifeq ($(PTHREAD), y) +LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ -lpthread +else LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++ +endif ifneq ($(X64), y) ifneq ($(ARM64), y) LIBS += -Wl,--large-address-aware diff --git a/src/win/win.c b/src/win/win.c index ff7726459..6d7cc86f9 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -1047,10 +1047,10 @@ plat_setfullscreen(int on) int dpi = win_get_dpi(hwndMain); /* Are we changing from the same state to the same state? */ - if ((!!on) == (!!video_fullscreen)) + if ((!!(on & 1)) == (!!video_fullscreen)) return; - if (on && video_fullscreen_first) { + if (on && (start_in_fullscreen || video_fullscreen_first)) { video_fullscreen |= 2; if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2134, (wchar_t *) IDS_2052) == 10) { video_fullscreen_first = 0; @@ -1060,13 +1060,14 @@ plat_setfullscreen(int on) } /* OK, claim the video. */ - win_mouse_close(); + if (!(on & 2)) + win_mouse_close(); /* Close the current mode, and open the new one. */ - video_fullscreen = on | 2; + video_fullscreen = (on & 1) | 2; if (vid_apis[vid_api].set_fs) - vid_apis[vid_api].set_fs(on); - if (!on) { + vid_apis[vid_api].set_fs(on & 1); + if (!(on & 1)) { plat_resize(scrnsz_x, scrnsz_y); if (vid_resize) { /* scale the screen base on DPI */ @@ -1089,6 +1090,9 @@ plat_setfullscreen(int on) } /* Main Window. */ + if (vid_resize >= 2) + MoveWindow(hwndMain, window_x, window_y, window_w, window_h, TRUE); + if (hide_status_bar) ResizeWindowByClientArea(hwndMain, temp_x, temp_y); else @@ -1111,26 +1115,31 @@ plat_setfullscreen(int on) } video_fullscreen &= 1; video_force_resize_set(1); - if (!on) + if (!(on & 1)) doresize = 1; win_mouse_init(); - /* Release video and make it redraw the screen. */ - device_force_redraw(); + if (!(on & 2)) { + /* Release video and make it redraw the screen. */ + device_force_redraw(); - /* Send a CTRL break code so CTRL does not get stuck. */ - keyboard_input(0, 0x01D); + /* Send a CTRL break code so CTRL does not get stuck. */ + keyboard_input(0, 0x01D); + } /* Finally, handle the host's mouse cursor. */ /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ show_cursor(video_fullscreen ? 0 : -1); - /* This is needed for OpenGL. */ - plat_vidapi_enable(0); - plat_vidapi_enable(1); + if (!(on & 2)) { + /* This is needed for OpenGL. */ + plat_vidapi_enable(0); + plat_vidapi_enable(1); + } } + void plat_vid_reload_options(void) { diff --git a/src/win/win_opengl.c b/src/win/win_opengl.c index 9d44fc47e..a73ffd981 100644 --- a/src/win/win_opengl.c +++ b/src/win/win_opengl.c @@ -64,6 +64,7 @@ static const int INIT_HEIGHT = 400; static const int BUFFERPIXELS = 4460544; /* Same size as render_buffer, pow(2048+64,2). */ static const int BUFFERBYTES = 17842176; /* Pixel is 4 bytes. */ static const int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ +static const int ROW_LENGTH = 2112; /* Source buffer row lenght (including padding) */ /** * @brief A dedicated OpenGL thread. @@ -106,7 +107,7 @@ static union */ typedef struct { - int y1, y2, w, h; + int w, h; void* buffer; /* Buffer for pixel transfer, allocated by gpu driver. */ volatile atomic_flag in_use; /* Is buffer currently in use. */ GLsync sync; /* Fence sync object used by opengl thread to track pixel transfer completion. */ @@ -641,18 +642,16 @@ static void opengl_main(void* param) SetEvent(sync_objects.resize); } - /* Clip to height. y2 can be out-of-bounds. */ - int sub_height = MIN(info->y2, info->h) - info->y1; - if (!GLAD_GL_ARB_buffer_storage) { /* Fallback method, copy data to pixel buffer. */ - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->w * sub_height * sizeof(uint32_t), info->buffer); + glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * read_pos, info->h * ROW_LENGTH * sizeof(uint32_t), info->buffer); } /* Update texture from pixel buffer. */ glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * read_pos); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, info->y1, info->w, sub_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, info->w, info->h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); /* Add fence to track when above gl commands are complete. */ info->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); @@ -808,21 +807,21 @@ static void opengl_main(void* param) CoUninitialize(); } -static void opengl_blit(int x, int y, int y1, int y2, int w, int h) +static void opengl_blit(int x, int y, int w, int h) { - if (y1 == y2 || h <= 0 || render_buffer == NULL || thread == NULL || + int yy; + + if ((h <= 0) || (buffer32 == NULL) || (thread == NULL) || atomic_flag_test_and_set(&blit_info[write_pos].in_use)) { video_blit_complete(); return; } - memcpy(blit_info[write_pos].buffer, &(render_buffer->dat)[y1 * w], w * (y2 - y1) * sizeof(uint32_t)); + memcpy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t)); video_blit_complete(); - blit_info[write_pos].y1 = y1; - blit_info[write_pos].y2 = y2; blit_info[write_pos].w = w; blit_info[write_pos].h = h; diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 8a748fb2b..ffd589ce0 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -229,29 +229,29 @@ sdl_stretch(int *w, int *h, int *x, int *y) static void -sdl_blit(int x, int y, int y1, int y2, int w, int h) +sdl_blit(int x, int y, int w, int h) { SDL_Rect r_src; int ret; - if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { + if (!sdl_enabled || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) { video_blit_complete(); return; } SDL_LockMutex(sdl_mutex); - r_src.x = 0; - r_src.y = y1; + r_src.x = x; + r_src.y = y; r_src.w = w; - r_src.h = y2 - y1; - SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4); + r_src.h = h; + SDL_UpdateTexture(sdl_tex, &r_src, &(buffer32->line[y][x]), (2048 + 64) * sizeof(uint32_t)); video_blit_complete(); SDL_RenderClear(sdl_render); - r_src.x = 0; - r_src.y = 0; + r_src.x = x; + r_src.y = y; r_src.w = w; r_src.h = h; @@ -277,6 +277,11 @@ sdl_destroy_window(void) static void sdl_destroy_texture(void) { + if (sdl_tex != NULL) { + SDL_DestroyTexture(sdl_tex); + sdl_tex = NULL; + } + /* SDL_DestroyRenderer also automatically destroys all associated textures. */ if (sdl_render != NULL) { SDL_DestroyRenderer(sdl_render); @@ -339,13 +344,8 @@ sdl_select_best_hw_driver(void) static void -sdl_reinit_texture(void) +sdl_init_texture(void) { - if (sdl_flags == -1) - return; - - sdl_destroy_texture(); - if (sdl_flags & RENDERER_HARDWARE) { sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); @@ -357,6 +357,17 @@ sdl_reinit_texture(void) } +static void +sdl_reinit_texture(void) +{ + if (sdl_flags == -1) + return; + + sdl_destroy_texture(); + sdl_init_texture(); +} + + void sdl_set_fs(int fs) { @@ -365,7 +376,6 @@ sdl_set_fs(int fs) SDL_LockMutex(sdl_mutex); sdl_enabled = 0; - sdl_destroy_texture(); if (fs) { ShowWindow(sdl_parent_hwnd, TRUE); @@ -408,7 +418,7 @@ sdl_set_fs(int fs) else sdl_flags &= ~RENDERER_FULL_SCREEN; - sdl_reinit_texture(); + // sdl_reinit_texture(); sdl_enabled = 1; SDL_UnlockMutex(sdl_mutex); } @@ -456,6 +466,7 @@ sdl_init_common(int flags) } sdl_win = SDL_CreateWindowFrom((void *)hwndRender); + sdl_init_texture(); sdl_set_fs(video_fullscreen & 1); /* Make sure we get a clean exit. */ @@ -554,16 +565,16 @@ sdl_enable(int enable) SDL_UnlockMutex(sdl_mutex); } + void sdl_reload(void) { - if (sdl_flags & RENDERER_HARDWARE) - { - SDL_LockMutex(sdl_mutex); + if (sdl_flags & RENDERER_HARDWARE) { + SDL_LockMutex(sdl_mutex); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); - sdl_reinit_texture(); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0"); + sdl_reinit_texture(); - SDL_UnlockMutex(sdl_mutex); - } -} \ No newline at end of file + SDL_UnlockMutex(sdl_mutex); + } +} diff --git a/src/win/win_specify_dim.c b/src/win/win_specify_dim.c index 52336ad5e..d4727c68b 100644 --- a/src/win/win_specify_dim.c +++ b/src/win/win_specify_dim.c @@ -140,11 +140,13 @@ SpecifyDimensionsDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM if (mouse_capture) ClipCursor(&r); - if (!(vid_resize & 2) && window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = r.left; window_y = r.top; - window_w = r.right - r.left; - window_h = r.bottom - r.top; + if (!(vid_resize & 2)) { + window_w = r.right - r.left; + window_h = r.bottom - r.top; + } } config_save(); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index a7cf7be8f..a778d60e7 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -697,11 +697,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) window_remember = !window_remember; CheckMenuItem(hmenu, IDM_VID_REMEMBER, window_remember ? MF_CHECKED : MF_UNCHECKED); GetWindowRect(hwnd, &rect); - if (!(vid_resize & 2) && window_remember) { + if (window_remember || (vid_resize & 2)) { window_x = rect.left; window_y = rect.top; - window_w = rect.right - rect.left; - window_h = rect.bottom - rect.top; + if (!(vid_resize & 2)) { + window_w = rect.right - rect.left; + window_h = rect.bottom - rect.top; + } } config_save(); break; @@ -978,11 +980,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) video_force_resize_set(1); } - if (window_remember) { + if (!(pos->flags & SWP_NOSIZE) && (window_remember || (vid_resize & 2))) { window_x = pos->x; window_y = pos->y; - window_w = pos->cx; - window_h = pos->cy; + if (!(vid_resize & 2)) { + window_w = pos->cx; + window_h = pos->cy; + } save_window_pos = 1; config_save(); } @@ -1375,6 +1379,7 @@ ui_init(int nCmdShow) MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); else { if (vid_resize >= 2) { + MoveWindow(hwnd, window_x, window_y, window_w, window_h, TRUE); scrnsz_x = fixed_size_x; scrnsz_y = fixed_size_y; } @@ -1422,7 +1427,8 @@ ui_init(int nCmdShow) } /* Initialize the mouse module. */ - win_mouse_init(); + if (!start_in_fullscreen && !video_fullscreen_first) + win_mouse_init(); /* * Before we can create the Render window, we first have @@ -1452,16 +1458,16 @@ ui_init(int nCmdShow) else plat_resize(scrnsz_x, scrnsz_y); + /* Initialize the rendering window, or fullscreen. */ + if (start_in_fullscreen || video_fullscreen_first) + plat_setfullscreen(3); + /* Fire up the machine. */ pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ plat_pause(0); - /* Initialize the rendering window, or fullscreen. */ - if (start_in_fullscreen) - plat_setfullscreen(1); - /* If so requested via the command line, inform the * application that started us of our HWND, using the * the hWnd and unique ID the application has given diff --git a/vcpkg.json b/vcpkg.json index 9fba60a48..eb9ed9b1d 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -8,6 +8,7 @@ "freetype", "libpng", "openal-soft", - "sdl2" + "sdl2", + "pthreads" ] } \ No newline at end of file