diff --git a/.ci/build.sh b/.ci/build.sh index f4f28dea6..cf420d4dd 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -288,7 +288,6 @@ then echo [-] Using MSYSTEM [$MSYSTEM] # Install dependencies only if we're in a new build and/or architecture. - freetype_dll="$cache_dir/freetype.$MSYSTEM.dll" if check_buildtag "$MSYSTEM" then # Update databases and keyring only if we're in a new build. @@ -333,9 +332,6 @@ then # Clean pacman cache when running under Jenkins to save disk space. [ "$CI" = "true" ] && rm -rf /var/cache/pacman/pkg - # Generate a new freetype DLL for this architecture. - rm -f "$freetype_dll" - # Save build tag to skip this later. Doing it here (once everything is # in place) is important to avoid potential issues with retried builds. save_buildtag "$MSYSTEM" @@ -796,10 +792,6 @@ then sevenzip="$pf/7-Zip/7z.exe" [ "$arch" = "32" -a -d "/c/Program Files (x86)" ] && pf="/c/Program Files (x86)" - # Archive freetype from cache or generate it from local MSYS installation. - [ ! -e "$freetype_dll" ] && .ci/static2dll.sh -p freetype2 /$MSYSTEM/lib/libfreetype.a "$freetype_dll" - cp -p "$freetype_dll" archive_tmp/freetype.dll - # Archive Ghostscript DLL from local official distribution installation. for gs in "$pf"/gs/gs*.*.* do diff --git a/.ci/static2dll.sh b/.ci/static2dll.sh deleted file mode 100755 index 030898752..000000000 --- a/.ci/static2dll.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/sh -# -# 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. -# -# Script for converting MinGW static libraries into a DLL. -# -# -# Authors: RichardG, -# -# Copyright 2021 RichardG. -# - -def_file="static2dll.def" -seen_file="static2dll.seen" -libs_file="static2dll.libs" - -find_lib() { - # Try to find a static library's file. - local msystem_lib="/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')/lib/lib" - if [ -e "$msystem_lib$1.a" ] - then - echo "$msystem_lib$1.a" - elif [ -e "$msystem_lib$1.dll.a" ] - then - echo "$msystem_lib$1.dll.a" - else - # Return dynamic reference to the library. - echo "-l$1" - return 1 - fi -} - -add_lib() { - # Always make sure this lib is listed after the last lib that depends on it. - old_libs=$(cat "$libs_file") - rm -f "$libs_file" - for lib in $old_libs - do - [ "$lib" != "$*" ] && echo "$lib" >> "$libs_file" - done - echo "$*" >> "$libs_file" - - # Add libstdc++ in the end if required. - if echo "$*" | grep -q "/" - then - grep -Eq -- "__cxa_|__gxx_" "$1" 2> /dev/null && add_lib -static -lstdc++ - fi - - # Add libiconv for libintl. - if echo "$*" | grep -q "libintl" - then - add_lib $(find_lib iconv) - fi - - # Add libuuid for glib. - if echo "$*" | grep -q "libglib" - then - add_lib $(find_lib uuid) - fi -} - -run_pkgconfig() { - local cache_file="static2dll.$1.cache" - if [ -e "$cache_file" ] - then - cat "$cache_file" - else - pkg-config --static --libs "$1" 2> /dev/null | tee "$cache_file" - fi -} - -parse_pkgconfig() { - # Parse arguments. - local layers=$1 - shift - local input_lib_name=$1 - shift - - # Don't process the same file again. - grep -q '^'$input_lib_name'$' "$seen_file" && return - echo $input_lib_name >> "$seen_file" - - echo "$layers" parse_pkgconfig $input_lib_name - - # Parse pkg-config arguments. - for arg in $* - do - local arg_base="$(echo $arg | cut -c1-2)" - if [ "x$arg_base" = "x-l" ] - then - # Don't process the same lib again. - local lib_name="$(echo $arg | cut -c3-)" - [ "x$lib_name" == "x$input_lib_name" ] && continue - - # Add lib path. - add_lib "$(find_lib $lib_name)" - - # Get this lib's dependencies through pkg-config. - local pkgconfig="$(run_pkgconfig "$lib_name")" - [ $? -eq 0 ] && parse_pkgconfig "$layers"'>' "$lib_name" $pkgconfig || echo $lib_name >> "$seen_file" - elif [ "x$(echo $arg_base | cut -c1)" = "x-" ] - then - # Ignore other arguments. - continue - else - # Add lib path. - add_lib "$arg" - fi - done -} - -# Parse arguments. -case $1 in - -p) # -p pkg_config_name static_lib_path out_dll - shift - base_pkgconfig=$(run_pkgconfig "$1") - base_path="$2" - base_name="$1" - ;; - - *) # pc_path static_lib_path out_dll - base_pkgconfig="$(grep ^Libs.private: $1 | cut -d: -f2-)" - base_path="$2" - base_name="$2" - ;; -esac - -# Check arguments. -if [ -z "$base_pkgconfig" -o -z "$base_path" -o -z "$base_name" ] -then - echo Usage: - echo static2dll.sh -p {pkgconfig_package_name} {static_lib_path} {out_dll_name} - echo static2dll.sh {pc_file_path} {static_lib_path} {out_dll_name} - exit 1 -fi - -# Produce .def file. -echo LIBRARY $(basename "$3") > "$def_file" -echo EXPORTS >> "$def_file" -nm "$base_path" | grep " [TC] " | sed "/ _/s// /" | awk '{ print $3 }' >> "$def_file" - -# Parse dependencies recursively. -rm -f "$seen_file" "$libs_file" "$libs_file.tmp" -touch "$seen_file" "$libs_file" -parse_pkgconfig '>' $base_name $base_pkgconfig - -# Produce final DLL. -dllwrap --def "$def_file" -o "$3" -Wl,--allow-multiple-definition "$base_path" $(cat "$libs_file") -status=$? -[ $status -eq 0 ] && rm -f "$def_file" "$seen_file" "$libs_file" "static2dll.*.cache" - -# Update final DLL timestamp. -touch -r "$base_path" "$3" - -exit $status diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index c4488ffd6..7d911e620 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -213,7 +213,7 @@ ali1489_write(uint16_t addr, uint8_t val, void *priv) ali1489_t *dev = (ali1489_t *) priv; uint8_t old; uint8_t irq; - const uint8_t irq_array[16] = { 0, 3, 4, 7, 0, 0, 0, 0, 9, 10, 5, 6, 11, 12, 14, 15 }; + const uint8_t irq_array[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 0, 11, 0, 12, 0, 14, 0, 15 }; switch (addr) { case 0x22: diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c index 46a49f118..894ebb100 100644 --- a/src/codegen/codegen_ops.c +++ b/src/codegen/codegen_ops.c @@ -128,6 +128,54 @@ RecompOpFn recomp_opcodes_0f[512] = { // clang-format on }; +RecompOpFn recomp_opcodes_0f_no_mmx[512] = { + // clang-format off + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on +}; + RecompOpFn recomp_opcodes_d8[512] = { // clang-format off /*16-bit data*/ diff --git a/src/codegen/codegen_ops.h b/src/codegen/codegen_ops.h index f92ba4f6d..5c19fb666 100644 --- a/src/codegen/codegen_ops.h +++ b/src/codegen/codegen_ops.h @@ -7,6 +7,7 @@ typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; +extern RecompOpFn recomp_opcodes_0f_no_mmx[512]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; extern RecompOpFn recomp_opcodes_da[512]; diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index c02e8a7c2..3934b4ac5 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -845,7 +845,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p switch (opcode) { case 0x0f: op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; over = 1; break; diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index c4b32c8a2..712fbe087 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1884,7 +1884,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p switch (opcode) { case 0x0f: op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; over = 1; break; diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index d49fcecbf..b0250fb7d 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -399,7 +399,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p last_prefix = 0x0f; #endif op_table = x86_dynarec_opcodes_0f; - recomp_op_table = recomp_opcodes_0f; + recomp_op_table = fpu_softfloat ? recomp_opcodes_0f_no_mmx : recomp_opcodes_0f; over = 1; break; @@ -634,11 +634,11 @@ generate_call: } opcode_3dnow = fastreadb(cs + opcode_pc); - if (recomp_opcodes_3DNOW[opcode_3dnow]) { + if (!fpu_softfloat && recomp_opcodes_3DNOW[opcode_3dnow]) { next_pc = opcode_pc + 1; op_table = (OpFn *) x86_dynarec_opcodes_3DNOW; - recomp_op_table = recomp_opcodes_3DNOW; + recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_3DNOW; opcode = opcode_3dnow; recomp_opcode_mask = 0xff; opcode_mask = 0xff; diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index 698a7899b..ae93aa80f 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -144,6 +144,54 @@ RecompOpFn recomp_opcodes_0f[512] = { // clang-format on }; +RecompOpFn recomp_opcodes_0f_no_mmx[512] = { + // clang-format off + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL, +/*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on +}; + RecompOpFn recomp_opcodes_3DNOW[256] = { // clang-format off #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 diff --git a/src/codegen_new/codegen_ops.h b/src/codegen_new/codegen_ops.h index 9cef07e15..352d95f13 100644 --- a/src/codegen_new/codegen_ops.h +++ b/src/codegen_new/codegen_ops.h @@ -9,6 +9,7 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t extern RecompOpFn recomp_opcodes[512]; extern RecompOpFn recomp_opcodes_0f[512]; +extern RecompOpFn recomp_opcodes_0f_no_mmx[512]; extern RecompOpFn recomp_opcodes_3DNOW[256]; extern RecompOpFn recomp_opcodes_d8[512]; extern RecompOpFn recomp_opcodes_d9[512]; diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index e345ee8d8..91449efeb 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -223,10 +223,11 @@ extern void x386_dynarec_log(const char *fmt, ...); static int opVPCEXT(uint32_t fetchdat) { - uint8_t b1, b2; + uint8_t b1; + uint8_t b2; uint16_t cent; time_t now; - struct tm *tm; + struct tm *tm = NULL; if (!is_vpc) /* only emulate this on Virtual PC machines */ return ILLEGAL(fetchdat); diff --git a/src/cpu/808x/CMakeLists.txt b/src/cpu/808x/CMakeLists.txt new file mode 100644 index 000000000..d29bdf4e0 --- /dev/null +++ b/src/cpu/808x/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# 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. +# +# CMake build script. +# +# Authors: David Hrdlička, +# +# Copyright 2020-2021 David Hrdlička. +# + +add_library(808x OBJECT queue.c) diff --git a/src/cpu/808x/queue.c b/src/cpu/808x/queue.c new file mode 100644 index 000000000..2eebde0ce --- /dev/null +++ b/src/cpu/808x/queue.c @@ -0,0 +1,190 @@ +/* + * 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. + * + * 808x CPU emulation, mostly ported from reenigne's XTCE, which + * is cycle-accurate. + * + * Authors: gloriouscow, + * Miran Grca, + * + * Copyright 2023 gloriouscow. + * Copyright 2023 Miran Grca. + */ +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86.h" +#include <86box/machine.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/ppi.h> +#include <86box/timer.h> +#include <86box/gdbstub.h> +// #include "808x.h" +#include "queue.h" + +/* TODO: Move to cpu.h so this can eventually be reused for 286+ as well. */ +#define QUEUE_MAX 6 + +typedef struct queue_t +{ + size_t size; + size_t len; + size_t back; + size_t front; + uint8_t q[QUEUE_MAX]; + uint16_t preload; + queue_delay_t delay; +} queue_t; + +static queue_t queue; + +#ifdef ENABLE_QUEUE_LOG +int queue_do_log = ENABLE_QUEUE_LOG; + +static void +queue_log(const char *fmt, ...) +{ + va_list ap; + + if (queue_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define queue_log(fmt, ...) +#endif + +void +queue_set_size(size_t size) +{ + if (size > QUEUE_MAX) + fatal("Requested prefetch queue of %i bytes is too big\n", size); + + queue.size = size; +} + +size_t +queue_get_len(void) +{ + return queue.len; +} + +int +queue_is_full(void) +{ + return (queue.len != queue.size); +} + +uint16_t +queue_get_preload(void) +{ + uint16_t ret = queue.preload; + queue.preload = 0x0000; + + return ret; +} + +int +queue_has_preload(void) +{ + return (queue.preload & FLAG_PRELOADED) ? 1 : 0; +} + +void +queue_set_preload(void) +{ + uint8_t byte; + + if (queue.len > 0) { + byte = queue_pop(); + queue.preload = ((uint16_t) byte) | FLAG_PRELOADED; + } else + fatal("Tried to preload with empty queue\n"); +} + +void +queue_push8(uint8_t byte) +{ + if (queue.len < queue.size) { + queue.q[queue.front] = byte; + queue.front = (queue.front + 1) % queue.size; + queue.len++; + + if (queue.len == 3) + queue.delay = DELAY_WRITE; + else + queue.delay = DELAY_NONE; + } else + fatal("Queue overrun\n"); +} + +void +queue_push16(uint16_t word) +{ + queue_push8((uint8_t) (word & 0xff)); + queue_push8((uint8_t) ((word >> 8) & 0xff)); +} + +uint8_t +queue_pop(void) +{ + uint8_t byte = 0xff; + + if (queue.len > 0) { + byte = queue.q[queue.back]; + + queue.back = (queue.back + 1) % queue.size; + queue.len--; + + if (queue.len >= 3) + queue.delay = DELAY_READ; + else + queue.delay = DELAY_NONE; + } else + fatal("Queue underrun\n"); + + return byte; +} + +queue_delay_t +queue_get_delay(void) +{ + return queue.delay; +} + +void +queue_flush(void) +{ + memset(&queue, 0x00, sizeof(queue_t)); + + queue.delay = DELAY_NONE; +} + +void +queue_init(void) +{ + queue_flush(); + + if (is8086) + queue_set_size(6); + else + queue_set_size(4); +} diff --git a/src/cpu/808x/queue.h b/src/cpu/808x/queue.h new file mode 100644 index 000000000..544455784 --- /dev/null +++ b/src/cpu/808x/queue.h @@ -0,0 +1,43 @@ +/* + * 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. + * + * Prefetch queue implementation header. + * + * Authors: gloriouscow, + * Miran Grca, + * + * Copyright 2023 gloriouscow. + * Copyright 2023 Miran Grca. + */ +#ifndef EMU_QUEUE_H +#define EMU_QUEUE_H + +typedef enum queue_delay_t +{ + DELAY_READ, + DELAY_WRITE, + DELAY_NONE +} queue_delay_t; + +#define FLAG_PRELOADED 0x8000 + +extern void queue_set_size(size_t size); +extern size_t queue_get_len(void); +extern int queue_is_full(void); +extern uint16_t queue_get_preload(void); +extern int queue_has_preload(void); +extern void queue_set_preload(void); +extern void queue_push8(uint8_t byte); +extern void queue_push16(uint16_t word); +extern uint8_t queue_pop(void); +extern queue_delay_t queue_get_delay(void); +extern void queue_flush(void); + +extern void queue_init(void); + +#endif /*EMU_QUEUE_H*/ diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 18aa06023..e4d8e71b2 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -14,7 +14,7 @@ # add_library(cpu OBJECT cpu.c cpu_table.c fpu.c x86.c 808x.c 386.c 386_common.c - 386_dynarec.c x86seg.c x87.c x87_timings.c 8080.c) + 386_dynarec.c x86_ops_mmx.c x86seg.c x87.c x87_timings.c 8080.c) if(AMD_K5) target_compile_definitions(cpu PRIVATE USE_AMD_K5) @@ -35,3 +35,6 @@ endif() add_subdirectory(softfloat) target_link_libraries(86Box softfloat) + +add_subdirectory(808x) +target_link_libraries(86Box 808x) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 257d23845..d633b9bb2 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1646,6 +1646,7 @@ cpu_set(void) cpu_exec = exec386; else cpu_exec = execx86; + mmx_init(); gdbstub_cpu_init(); } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 692600005..3d6d0622a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -850,4 +850,9 @@ extern void cpu_fast_off_reset(void); extern void smi_raise(void); extern void nmi_raise(void); +extern MMX_REG *MMP[8]; +extern uint16_t *MMEP[8]; + +extern void mmx_init(void); + #endif /*EMU_CPU_H*/ diff --git a/src/cpu/x86_ops_3dnow.h b/src/cpu/x86_ops_3dnow.h index eb7a35ace..ff657d708 100644 --- a/src/cpu/x86_ops_3dnow.h +++ b/src/cpu/x86_ops_3dnow.h @@ -36,17 +36,20 @@ static int opPAVGUSB(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] + src.b[0] + 1) >> 1; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] + src.b[1] + 1) >> 1; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] + src.b[2] + 1) >> 1; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] + src.b[3] + 1) >> 1; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] + src.b[4] + 1) >> 1; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] + src.b[5] + 1) >> 1; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] + src.b[6] + 1) >> 1; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] + src.b[7] + 1) >> 1; + dst->b[0] = (dst->b[0] + src.b[0] + 1) >> 1; + dst->b[1] = (dst->b[1] + src.b[1] + 1) >> 1; + dst->b[2] = (dst->b[2] + src.b[2] + 1) >> 1; + dst->b[3] = (dst->b[3] + src.b[3] + 1) >> 1; + dst->b[4] = (dst->b[4] + src.b[4] + 1) >> 1; + dst->b[5] = (dst->b[5] + src.b[5] + 1) >> 1; + dst->b[6] = (dst->b[6] + src.b[6] + 1) >> 1; + dst->b[7] = (dst->b[7] + src.b[7] + 1) >> 1; + + MMX_SETEXP(cpu_reg); return 0; } @@ -54,11 +57,14 @@ static int opPF2ID(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].sl[0] = (int32_t) src.f[0]; - cpu_state.MM[cpu_reg].sl[1] = (int32_t) src.f[1]; + dst->sl[0] = (int32_t) src.f[0]; + dst->sl[1] = (int32_t) src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -66,11 +72,14 @@ static int opPF2IW(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].sw[0] = (int32_t) src.f[0]; - cpu_state.MM[cpu_reg].sw[1] = (int32_t) src.f[1]; + dst->sw[0] = (int32_t) src.f[0]; + dst->sw[1] = (int32_t) src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -78,13 +87,16 @@ static int opPFACC(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); float tempf; MMX_GETSRC(); - tempf = cpu_state.MM[cpu_reg].f[0] + cpu_state.MM[cpu_reg].f[1]; - cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1]; - cpu_state.MM[cpu_reg].f[0] = tempf; + tempf = dst->f[0] + dst->f[1]; + dst->f[1] = src.f[0] + src.f[1]; + dst->f[0] = tempf; + + MMX_SETEXP(cpu_reg); return 0; } @@ -92,13 +104,16 @@ static int opPFNACC(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); float tempf; MMX_GETSRC(); - tempf = cpu_state.MM[cpu_reg].f[0] - cpu_state.MM[cpu_reg].f[1]; - cpu_state.MM[cpu_reg].f[1] = src.f[0] - src.f[1]; - cpu_state.MM[cpu_reg].f[0] = tempf; + tempf = dst->f[0] - dst->f[1]; + dst->f[1] = src.f[0] - src.f[1]; + dst->f[0] = tempf; + + MMX_SETEXP(cpu_reg); return 0; } @@ -106,13 +121,16 @@ static int opPFPNACC(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); float tempf; MMX_GETSRC(); - tempf = cpu_state.MM[cpu_reg].f[0] - cpu_state.MM[cpu_reg].f[1]; - cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1]; - cpu_state.MM[cpu_reg].f[0] = tempf; + tempf = dst->f[0] - dst->f[1]; + dst->f[1] = src.f[0] + src.f[1]; + dst->f[0] = tempf; + + MMX_SETEXP(cpu_reg); return 0; } @@ -120,15 +138,18 @@ static int opPSWAPD(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); float tempf, tempf2; MMX_GETSRC(); /* We have to do this in case source and destination overlap. */ - tempf = src.f[0]; - tempf2 = src.f[1]; - cpu_state.MM[cpu_reg].f[1] = tempf; - cpu_state.MM[cpu_reg].f[0] = tempf2; + tempf = src.f[0]; + tempf2 = src.f[1]; + dst->f[1] = tempf; + dst->f[0] = tempf2; + + MMX_SETEXP(cpu_reg); return 0; } @@ -136,11 +157,14 @@ static int opPFADD(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] += src.f[0]; - cpu_state.MM[cpu_reg].f[1] += src.f[1]; + dst->f[0] += src.f[0]; + dst->f[1] += src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -148,11 +172,14 @@ static int opPFCMPEQ(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] == src.f[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] == src.f[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->f[0] == src.f[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->f[1] == src.f[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -160,11 +187,14 @@ static int opPFCMPGE(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] >= src.f[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] >= src.f[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->f[0] >= src.f[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->f[1] >= src.f[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -172,11 +202,14 @@ static int opPFCMPGT(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] > src.f[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] > src.f[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->f[0] > src.f[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->f[1] > src.f[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -184,13 +217,16 @@ static int opPFMAX(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - if (src.f[0] > cpu_state.MM[cpu_reg].f[0]) - cpu_state.MM[cpu_reg].f[0] = src.f[0]; - if (src.f[1] > cpu_state.MM[cpu_reg].f[1]) - cpu_state.MM[cpu_reg].f[1] = src.f[1]; + if (src.f[0] > dst->f[0]) + dst->f[0] = src.f[0]; + if (src.f[1] > dst->f[1]) + dst->f[1] = src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -198,13 +234,16 @@ static int opPFMIN(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - if (src.f[0] < cpu_state.MM[cpu_reg].f[0]) - cpu_state.MM[cpu_reg].f[0] = src.f[0]; - if (src.f[1] < cpu_state.MM[cpu_reg].f[1]) - cpu_state.MM[cpu_reg].f[1] = src.f[1]; + if (src.f[0] < dst->f[0]) + dst->f[0] = src.f[0]; + if (src.f[1] < dst->f[1]) + dst->f[1] = src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -212,24 +251,29 @@ static int opPFMUL(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] *= src.f[0]; - cpu_state.MM[cpu_reg].f[1] *= src.f[1]; + dst->f[0] *= src.f[0]; + dst->f[1] *= src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } static int opPFRCP(uint32_t fetchdat) { + MMX_REG *dst = MMX_GETREGP(cpu_reg); + union { uint32_t i; float f; } src; if (cpu_mod == 3) { - src.f = cpu_state.MM[cpu_rm].f[0]; + src.f = (MMX_GETREG(cpu_rm)).f[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_READ(cpu_state.ea_seg); @@ -239,8 +283,10 @@ opPFRCP(uint32_t fetchdat) CLOCK_CYCLES(2); } - cpu_state.MM[cpu_reg].f[0] = 1.0 / src.f; - cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0]; + dst->f[0] = 1.0 / src.f; + dst->f[1] = dst->f[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -249,11 +295,14 @@ static int opPFRCPIT1(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] = src.f[0]; - cpu_state.MM[cpu_reg].f[1] = src.f[1]; + dst->f[0] = src.f[0]; + dst->f[1] = src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -261,24 +310,29 @@ static int opPFRCPIT2(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] = src.f[0]; - cpu_state.MM[cpu_reg].f[1] = src.f[1]; + dst->f[0] = src.f[0]; + dst->f[1] = src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } static int opPFRSQRT(uint32_t fetchdat) { + MMX_REG *dst = MMX_GETREGP(cpu_reg); + union { uint32_t i; float f; } src; if (cpu_mod == 3) { - src.f = cpu_state.MM[cpu_rm].f[0]; + src.f = (MMX_GETREG(cpu_rm)).f[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_READ(cpu_state.ea_seg); @@ -288,8 +342,10 @@ opPFRSQRT(uint32_t fetchdat) CLOCK_CYCLES(2); } - cpu_state.MM[cpu_reg].f[0] = 1.0 / sqrt(src.f); - cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0]; + dst->f[0] = 1.0 / sqrt(src.f); + dst->f[1] = dst->f[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -308,11 +364,14 @@ static int opPFSUB(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] -= src.f[0]; - cpu_state.MM[cpu_reg].f[1] -= src.f[1]; + dst->f[0] -= src.f[0]; + dst->f[1] -= src.f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -320,11 +379,14 @@ static int opPFSUBR(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] = src.f[0] - cpu_state.MM[cpu_reg].f[0]; - cpu_state.MM[cpu_reg].f[1] = src.f[1] - cpu_state.MM[cpu_reg].f[1]; + dst->f[0] = src.f[0] - dst->f[0]; + dst->f[1] = src.f[1] - dst->f[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -332,11 +394,14 @@ static int opPI2FD(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] = (float) src.sl[0]; - cpu_state.MM[cpu_reg].f[1] = (float) src.sl[1]; + dst->f[0] = (float) src.sl[0]; + dst->f[1] = (float) src.sl[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -344,37 +409,46 @@ static int opPI2FW(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); MMX_GETSRC(); - cpu_state.MM[cpu_reg].f[0] = (float) src.sw[0]; - cpu_state.MM[cpu_reg].f[1] = (float) src.sw[1]; + dst->f[0] = (float) src.sw[0]; + dst->f[1] = (float) src.sw[1]; + + MMX_SETEXP(cpu_reg); return 0; } static int opPMULHRW(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].w[0] = (((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) cpu_state.MM[cpu_rm].sw[0]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[1] = (((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) cpu_state.MM[cpu_rm].sw[1]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[2] = (((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) cpu_state.MM[cpu_rm].sw[2]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[3] = (((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) cpu_state.MM[cpu_rm].sw[3]) + 0x8000) >> 16; + src = MMX_GETREG(cpu_rm); + + dst->w[0] = (((int32_t) dst->sw[0] * (int32_t) src.sw[0]) + 0x8000) >> 16; + dst->w[1] = (((int32_t) dst->sw[1] * (int32_t) src.sw[1]) + 0x8000) >> 16; + dst->w[2] = (((int32_t) dst->sw[2] * (int32_t) src.sw[2]) + 0x8000) >> 16; + dst->w[3] = (((int32_t) dst->sw[3] * (int32_t) src.sw[3]) + 0x8000) >> 16; CLOCK_CYCLES(1); } else { - MMX_REG src; - SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].w[0] = ((int32_t) (cpu_state.MM[cpu_reg].sw[0] * (int32_t) src.sw[0]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[1] = ((int32_t) (cpu_state.MM[cpu_reg].sw[1] * (int32_t) src.sw[1]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[2] = ((int32_t) (cpu_state.MM[cpu_reg].sw[2] * (int32_t) src.sw[2]) + 0x8000) >> 16; - cpu_state.MM[cpu_reg].w[3] = ((int32_t) (cpu_state.MM[cpu_reg].sw[3] * (int32_t) src.sw[3]) + 0x8000) >> 16; + dst->w[0] = ((int32_t) (dst->sw[0] * (int32_t) src.sw[0]) + 0x8000) >> 16; + dst->w[1] = ((int32_t) (dst->sw[1] * (int32_t) src.sw[1]) + 0x8000) >> 16; + dst->w[2] = ((int32_t) (dst->sw[2] * (int32_t) src.sw[2]) + 0x8000) >> 16; + dst->w[3] = ((int32_t) (dst->sw[3] * (int32_t) src.sw[3]) + 0x8000) >> 16; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 9e00249ca..f2b07a1c4 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -43,6 +43,132 @@ opSYSEXIT(uint32_t fetchdat) return ret; } +static int +sf_fx_save_stor_common(uint32_t fetchdat, int bits) +{ + uint8_t fxinst = 0; + uint32_t tag_byte; + unsigned index; + floatx80 reg; + + if (CPUID < 0x650) + return ILLEGAL(fetchdat); + + FP_ENTER(); + + if (bits == 32) { + fetch_ea_32(fetchdat); + } else { + fetch_ea_16(fetchdat); + } + + if (cpu_state.eaaddr & 0xf) { + x386_dynarec_log("Effective address %08X not on 16-byte boundary\n", cpu_state.eaaddr); + x86gpf(NULL, 0); + return cpu_state.abrt; + } + + fxinst = (rmdat >> 3) & 7; + + if ((fxinst > 1) || (cpu_mod == 3)) { + x86illegal(); + return cpu_state.abrt; + } + + FP_ENTER(); + + if (fxinst == 1) { + /* FXRSTOR */ + fpu_state.cwd = readmemw(easeg, cpu_state.eaaddr); + fpu_state.swd = readmemw(easeg, cpu_state.eaaddr + 2); + fpu_state.tos = (fpu_state.swd >> 11) & 7; + + /* always set bit 6 as '1 */ + fpu_state.cwd = (fpu_state.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; + + /* Restore x87 FPU Opcode */ + /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ + fpu_state.foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; + + fpu_state.fip = readmeml(easeg, cpu_state.eaaddr + 8); + fpu_state.fcs = readmemw(easeg, cpu_state.eaaddr + 12); + + tag_byte = readmemb(easeg, cpu_state.eaaddr + 4); + + fpu_state.fdp = readmeml(easeg, cpu_state.eaaddr + 16); + fpu_state.fds = readmemw(easeg, cpu_state.eaaddr + 20); + + /* load i387 register file */ + for (index = 0; index < 8; index++) { + reg.fraction = readmemq(easeg, cpu_state.eaaddr + (index * 16) + 32); + reg.exp = readmemw(easeg, cpu_state.eaaddr + (index * 16) + 40); + + // update tag only if it is not empty + FPU_save_regi_tag(reg, IS_TAG_EMPTY(index) ? X87_TAG_EMPTY : FPU_tagof(reg), index); + } + + fpu_state.tag = unpack_FPU_TW(tag_byte); + + /* check for unmasked exceptions */ + if (fpu_state.swd & ~fpu_state.cwd & FPU_CW_Exceptions_Mask) { + /* set the B and ES bits in the status-word */ + fpu_state.swd |= (FPU_SW_Summary | FPU_SW_Backward); + } else { + /* clear the B and ES bits in the status-word */ + fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward); + } + + CLOCK_CYCLES((cr0 & 1) ? 34 : 44); + } else { + /* FXSAVE */ + writememw(easeg, cpu_state.eaaddr, i387_get_control_word()); + writememw(easeg, cpu_state.eaaddr + 2, i387_get_status_word()); + writememw(easeg, cpu_state.eaaddr + 4, pack_FPU_TW(fpu_state.tag)); + + /* x87 FPU Opcode (16 bits) */ + /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ + writememw(easeg, cpu_state.eaaddr + 6, fpu_state.foo); + + /* + * x87 FPU IP Offset (32/64 bits) + * The contents of this field differ depending on the current + * addressing mode (16/32/64 bit) when the FXSAVE instruction was executed: + * + 64-bit mode - 64-bit IP offset + * + 32-bit mode - 32-bit IP offset + * + 16-bit mode - low 16 bits are IP offset; high 16 bits are reserved. + * x87 CS FPU IP Selector + * + 16 bit, in 16/32 bit mode only + */ + writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip); + writememl(easeg, cpu_state.eaaddr + 12, fpu_state.fcs); + + /* + * x87 FPU Instruction Operand (Data) Pointer Offset (32/64 bits) + * The contents of this field differ depending on the current + * addressing mode (16/32 bit) when the FXSAVE instruction was executed: + * + 64-bit mode - 64-bit offset + * + 32-bit mode - 32-bit offset + * + 16-bit mode - low 16 bits are offset; high 16 bits are reserved. + * x87 DS FPU Instruction Operand (Data) Pointer Selector + * + 16 bit, in 16/32 bit mode only + */ + writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp); + writememl(easeg, cpu_state.eaaddr + 20, fpu_state.fds); + + /* store i387 register file */ + for (index = 0; index < 8; index++) { + const floatx80 fp = FPU_read_regi(index); + + writememq(easeg, cpu_state.eaaddr + (index * 16) + 32, fp.fraction); + writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.exp); + } + + CLOCK_CYCLES((cr0 & 1) ? 56 : 67); + } + + return cpu_state.abrt; +} + static int fx_save_stor_common(uint32_t fetchdat, int bits) { @@ -253,12 +379,18 @@ fx_save_stor_common(uint32_t fetchdat, int bits) static int opFXSAVESTOR_a16(uint32_t fetchdat) { + if (fpu_softfloat) + return sf_fx_save_stor_common(fetchdat, 16); + return fx_save_stor_common(fetchdat, 16); } static int opFXSAVESTOR_a32(uint32_t fetchdat) { + if (fpu_softfloat) + return sf_fx_save_stor_common(fetchdat, 32); + return fx_save_stor_common(fetchdat, 32); } diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index 940e2ea8e..60ed873e4 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -51,8 +51,10 @@ opSETALC(uint32_t fetchdat) static int opF6_a16(uint32_t fetchdat) { - int tempws, tempws2 = 0; - uint16_t tempw, src16; + int tempws = 0; + int tempws2 = 0; + uint16_t tempw = 0; + uint16_t src16; uint8_t src, dst; int8_t temps; @@ -167,8 +169,10 @@ opF6_a16(uint32_t fetchdat) static int opF6_a32(uint32_t fetchdat) { - int tempws, tempws2 = 0; - uint16_t tempw, src16; + int tempws = 0; + int tempws2 = 0; + uint16_t tempw = 0; + uint16_t src16; uint8_t src, dst; int8_t temps; @@ -282,10 +286,13 @@ opF6_a32(uint32_t fetchdat) static int opF7_w_a16(uint32_t fetchdat) { - uint32_t templ, templ2 = 0; - int tempws, tempws2 = 0; + uint32_t templ; + uint32_t templ2 = 0; + int tempws; + int tempws2 = 0; int16_t temps16; - uint16_t src, dst; + uint16_t src; + uint16_t dst; fetch_ea_16(fetchdat); if (cpu_mod != 3) @@ -392,8 +399,10 @@ opF7_w_a16(uint32_t fetchdat) static int opF7_w_a32(uint32_t fetchdat) { - uint32_t templ, templ2 = 0; - int tempws, tempws2 = 1; + uint32_t templ; + uint32_t templ2 = 0; + int tempws; + int tempws2 = 1; int16_t temps16; uint16_t src, dst; diff --git a/src/cpu/x86_ops_mmx.c b/src/cpu/x86_ops_mmx.c new file mode 100644 index 000000000..1afc4fba2 --- /dev/null +++ b/src/cpu/x86_ops_mmx.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include +#ifndef INFINITY +# define INFINITY (__builtin_inff()) +#endif +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include "x86.h" +#include "x87.h" +#include <86box/nmi.h> +#include <86box/mem.h> +#include <86box/smram.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/keyboard.h> +#include <86box/timer.h> +#include "386_common.h" +#include "x86_flags.h" +#include "x86seg.h" + +MMX_REG *MMP[8]; +uint16_t *MMEP[8]; + +static uint16_t MME[8]; + +#define MMX_GETREGP(r) fpu_softfloat ? ((MMX_REG *) &fpu_state.st_space[r].fraction) : &(cpu_state.MM[r]) +void +mmx_init(void) +{ + memset(MME, 0xff, sizeof(MME)); + + for (uint8_t i = 0; i < 8; i++) { + if (fpu_softfloat) { + MMP[i] = (MMX_REG *) &fpu_state.st_space[i].fraction; + MMEP[i] = (uint16_t *) &fpu_state.st_space[i].exp; + } else { + MMP[i] = &(cpu_state.MM[i]); + MMEP[i] = &(MME[i]); + } + } +} diff --git a/src/cpu/x86_ops_mmx.h b/src/cpu/x86_ops_mmx.h index d270b728f..47751d059 100644 --- a/src/cpu/x86_ops_mmx.h +++ b/src/cpu/x86_ops_mmx.h @@ -3,9 +3,15 @@ #define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val))) #define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val))) +#define MMX_GETREGP(r) MMP[r] +#define MMX_GETREG(r) *(MMP[r]) + +#define MMX_SETEXP(r) \ + *(MMEP[r]) = 0xffff + #define MMX_GETSRC() \ if (cpu_mod == 3) { \ - src = cpu_state.MM[cpu_rm]; \ + src = MMX_GETREG(cpu_rm); \ CLOCK_CYCLES(1); \ } else { \ SEG_CHECK_READ(cpu_state.ea_seg); \ diff --git a/src/cpu/x86_ops_mmx_arith.h b/src/cpu/x86_ops_mmx_arith.h index e473f8ec5..642e99c8a 100644 --- a/src/cpu/x86_ops_mmx_arith.h +++ b/src/cpu/x86_ops_mmx_arith.h @@ -2,19 +2,25 @@ static int opPADDB_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] += src.b[0]; - cpu_state.MM[cpu_reg].b[1] += src.b[1]; - cpu_state.MM[cpu_reg].b[2] += src.b[2]; - cpu_state.MM[cpu_reg].b[3] += src.b[3]; - cpu_state.MM[cpu_reg].b[4] += src.b[4]; - cpu_state.MM[cpu_reg].b[5] += src.b[5]; - cpu_state.MM[cpu_reg].b[6] += src.b[6]; - cpu_state.MM[cpu_reg].b[7] += src.b[7]; + dst->b[0] += src.b[0]; + dst->b[1] += src.b[1]; + dst->b[2] += src.b[2]; + dst->b[3] += src.b[3]; + dst->b[4] += src.b[4]; + dst->b[5] += src.b[5]; + dst->b[6] += src.b[6]; + dst->b[7] += src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -22,19 +28,25 @@ static int opPADDB_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] += src.b[0]; - cpu_state.MM[cpu_reg].b[1] += src.b[1]; - cpu_state.MM[cpu_reg].b[2] += src.b[2]; - cpu_state.MM[cpu_reg].b[3] += src.b[3]; - cpu_state.MM[cpu_reg].b[4] += src.b[4]; - cpu_state.MM[cpu_reg].b[5] += src.b[5]; - cpu_state.MM[cpu_reg].b[6] += src.b[6]; - cpu_state.MM[cpu_reg].b[7] += src.b[7]; + dst->b[0] += src.b[0]; + dst->b[1] += src.b[1]; + dst->b[2] += src.b[2]; + dst->b[3] += src.b[3]; + dst->b[4] += src.b[4]; + dst->b[5] += src.b[5]; + dst->b[6] += src.b[6]; + dst->b[7] += src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -43,15 +55,21 @@ static int opPADDW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] += src.w[0]; - cpu_state.MM[cpu_reg].w[1] += src.w[1]; - cpu_state.MM[cpu_reg].w[2] += src.w[2]; - cpu_state.MM[cpu_reg].w[3] += src.w[3]; + dst->w[0] += src.w[0]; + dst->w[1] += src.w[1]; + dst->w[2] += src.w[2]; + dst->w[3] += src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -59,15 +77,21 @@ static int opPADDW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] += src.w[0]; - cpu_state.MM[cpu_reg].w[1] += src.w[1]; - cpu_state.MM[cpu_reg].w[2] += src.w[2]; - cpu_state.MM[cpu_reg].w[3] += src.w[3]; + dst->w[0] += src.w[0]; + dst->w[1] += src.w[1]; + dst->w[2] += src.w[2]; + dst->w[3] += src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -76,13 +100,19 @@ static int opPADDD_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] += src.l[0]; - cpu_state.MM[cpu_reg].l[1] += src.l[1]; + dst->l[0] += src.l[0]; + dst->l[1] += src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -90,13 +120,19 @@ static int opPADDD_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] += src.l[0]; - cpu_state.MM[cpu_reg].l[1] += src.l[1]; + dst->l[0] += src.l[0]; + dst->l[1] += src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -105,19 +141,25 @@ static int opPADDSB_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]); + dst->sb[0] = SSATB(dst->sb[0] + src.sb[0]); + dst->sb[1] = SSATB(dst->sb[1] + src.sb[1]); + dst->sb[2] = SSATB(dst->sb[2] + src.sb[2]); + dst->sb[3] = SSATB(dst->sb[3] + src.sb[3]); + dst->sb[4] = SSATB(dst->sb[4] + src.sb[4]); + dst->sb[5] = SSATB(dst->sb[5] + src.sb[5]); + dst->sb[6] = SSATB(dst->sb[6] + src.sb[6]); + dst->sb[7] = SSATB(dst->sb[7] + src.sb[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -125,19 +167,25 @@ static int opPADDSB_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]); + dst->sb[0] = SSATB(dst->sb[0] + src.sb[0]); + dst->sb[1] = SSATB(dst->sb[1] + src.sb[1]); + dst->sb[2] = SSATB(dst->sb[2] + src.sb[2]); + dst->sb[3] = SSATB(dst->sb[3] + src.sb[3]); + dst->sb[4] = SSATB(dst->sb[4] + src.sb[4]); + dst->sb[5] = SSATB(dst->sb[5] + src.sb[5]); + dst->sb[6] = SSATB(dst->sb[6] + src.sb[6]); + dst->sb[7] = SSATB(dst->sb[7] + src.sb[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -146,19 +194,25 @@ static int opPADDUSB_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]); - cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]); - cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]); - cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]); + dst->b[0] = USATB(dst->b[0] + src.b[0]); + dst->b[1] = USATB(dst->b[1] + src.b[1]); + dst->b[2] = USATB(dst->b[2] + src.b[2]); + dst->b[3] = USATB(dst->b[3] + src.b[3]); + dst->b[4] = USATB(dst->b[4] + src.b[4]); + dst->b[5] = USATB(dst->b[5] + src.b[5]); + dst->b[6] = USATB(dst->b[6] + src.b[6]); + dst->b[7] = USATB(dst->b[7] + src.b[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -166,19 +220,25 @@ static int opPADDUSB_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]); - cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]); - cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]); - cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]); + dst->b[0] = USATB(dst->b[0] + src.b[0]); + dst->b[1] = USATB(dst->b[1] + src.b[1]); + dst->b[2] = USATB(dst->b[2] + src.b[2]); + dst->b[3] = USATB(dst->b[3] + src.b[3]); + dst->b[4] = USATB(dst->b[4] + src.b[4]); + dst->b[5] = USATB(dst->b[5] + src.b[5]); + dst->b[6] = USATB(dst->b[6] + src.b[6]); + dst->b[7] = USATB(dst->b[7] + src.b[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -187,15 +247,21 @@ static int opPADDSW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]); + dst->sw[0] = SSATW(dst->sw[0] + src.sw[0]); + dst->sw[1] = SSATW(dst->sw[1] + src.sw[1]); + dst->sw[2] = SSATW(dst->sw[2] + src.sw[2]); + dst->sw[3] = SSATW(dst->sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -203,15 +269,21 @@ static int opPADDSW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]); + dst->sw[0] = SSATW(dst->sw[0] + src.sw[0]); + dst->sw[1] = SSATW(dst->sw[1] + src.sw[1]); + dst->sw[2] = SSATW(dst->sw[2] + src.sw[2]); + dst->sw[3] = SSATW(dst->sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -220,15 +292,21 @@ static int opPADDUSW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]); - cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]); - cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]); - cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]); + dst->w[0] = USATW(dst->w[0] + src.w[0]); + dst->w[1] = USATW(dst->w[1] + src.w[1]); + dst->w[2] = USATW(dst->w[2] + src.w[2]); + dst->w[3] = USATW(dst->w[3] + src.w[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -236,15 +314,21 @@ static int opPADDUSW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]); - cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]); - cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]); - cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]); + dst->w[0] = USATW(dst->w[0] + src.w[0]); + dst->w[1] = USATW(dst->w[1] + src.w[1]); + dst->w[2] = USATW(dst->w[2] + src.w[2]); + dst->w[3] = USATW(dst->w[3] + src.w[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -253,20 +337,26 @@ static int opPMADDWD_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000) - cpu_state.MM[cpu_reg].l[0] = 0x80000000; + if (dst->l[0] == 0x80008000 && src.l[0] == 0x80008000) + dst->l[0] = 0x80000000; else - cpu_state.MM[cpu_reg].sl[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) src.sw[0]) + ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) src.sw[1]); + dst->sl[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) + ((int32_t) dst->sw[1] * (int32_t) src.sw[1]); - if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000) - cpu_state.MM[cpu_reg].l[1] = 0x80000000; + if (dst->l[1] == 0x80008000 && src.l[1] == 0x80008000) + dst->l[1] = 0x80000000; else - cpu_state.MM[cpu_reg].sl[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) src.sw[2]) + ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) src.sw[3]); + dst->sl[1] = ((int32_t) dst->sw[2] * (int32_t) src.sw[2]) + ((int32_t) dst->sw[3] * (int32_t) src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -274,20 +364,26 @@ static int opPMADDWD_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000) - cpu_state.MM[cpu_reg].l[0] = 0x80000000; + if (dst->l[0] == 0x80008000 && src.l[0] == 0x80008000) + dst->l[0] = 0x80000000; else - cpu_state.MM[cpu_reg].sl[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) src.sw[0]) + ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) src.sw[1]); + dst->sl[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) + ((int32_t) dst->sw[1] * (int32_t) src.sw[1]); - if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000) - cpu_state.MM[cpu_reg].l[1] = 0x80000000; + if (dst->l[1] == 0x80008000 && src.l[1] == 0x80008000) + dst->l[1] = 0x80000000; else - cpu_state.MM[cpu_reg].sl[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) src.sw[2]) + ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) src.sw[3]); + dst->sl[1] = ((int32_t) dst->sw[2] * (int32_t) src.sw[2]) + ((int32_t) dst->sw[3] * (int32_t) src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -295,114 +391,126 @@ opPMADDWD_a32(uint32_t fetchdat) static int opPMULLW_a16(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); - if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0]; - cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1]; - cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2]; - cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3]; - CLOCK_CYCLES(1); - } else { - MMX_REG src; + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) + src = MMX_GETREG(cpu_rm); + else { SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].w[0] *= src.w[0]; - cpu_state.MM[cpu_reg].w[1] *= src.w[1]; - cpu_state.MM[cpu_reg].w[2] *= src.w[2]; - cpu_state.MM[cpu_reg].w[3] *= src.w[3]; - CLOCK_CYCLES(2); + CLOCK_CYCLES(1); } + dst->w[0] *= src.w[0]; + dst->w[1] *= src.w[1]; + dst->w[2] *= src.w[2]; + dst->w[3] *= src.w[3]; + CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_reg); + return 0; } static int opPMULLW_a32(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); - if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0]; - cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1]; - cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2]; - cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3]; - CLOCK_CYCLES(1); - } else { - MMX_REG src; + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) + src = MMX_GETREG(cpu_rm); + else { SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].w[0] *= src.w[0]; - cpu_state.MM[cpu_reg].w[1] *= src.w[1]; - cpu_state.MM[cpu_reg].w[2] *= src.w[2]; - cpu_state.MM[cpu_reg].w[3] *= src.w[3]; - CLOCK_CYCLES(2); + CLOCK_CYCLES(1); } + dst->w[0] *= src.w[0]; + dst->w[1] *= src.w[1]; + dst->w[2] *= src.w[2]; + dst->w[3] *= src.w[3]; + CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_reg); + return 0; } static int opPMULHW_a16(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); - if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].w[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) cpu_state.MM[cpu_rm].sw[0]) >> 16; - cpu_state.MM[cpu_reg].w[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) cpu_state.MM[cpu_rm].sw[1]) >> 16; - cpu_state.MM[cpu_reg].w[2] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) cpu_state.MM[cpu_rm].sw[2]) >> 16; - cpu_state.MM[cpu_reg].w[3] = ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) cpu_state.MM[cpu_rm].sw[3]) >> 16; - CLOCK_CYCLES(1); - } else { - MMX_REG src; + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) + src = MMX_GETREG(cpu_rm); + else { SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].w[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) src.sw[0]) >> 16; - cpu_state.MM[cpu_reg].w[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) src.sw[1]) >> 16; - cpu_state.MM[cpu_reg].w[2] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) src.sw[2]) >> 16; - cpu_state.MM[cpu_reg].w[3] = ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) src.sw[3]) >> 16; - CLOCK_CYCLES(2); + CLOCK_CYCLES(1); } + dst->w[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) >> 16; + dst->w[1] = ((int32_t) dst->sw[1] * (int32_t) src.sw[1]) >> 16; + dst->w[2] = ((int32_t) dst->sw[2] * (int32_t) src.sw[2]) >> 16; + dst->w[3] = ((int32_t) dst->sw[3] * (int32_t) src.sw[3]) >> 16; + CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_reg); + return 0; } static int opPMULHW_a32(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); - if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].w[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) cpu_state.MM[cpu_rm].sw[0]) >> 16; - cpu_state.MM[cpu_reg].w[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) cpu_state.MM[cpu_rm].sw[1]) >> 16; - cpu_state.MM[cpu_reg].w[2] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) cpu_state.MM[cpu_rm].sw[2]) >> 16; - cpu_state.MM[cpu_reg].w[3] = ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) cpu_state.MM[cpu_rm].sw[3]) >> 16; - CLOCK_CYCLES(1); - } else { - MMX_REG src; + dst = MMX_GETREGP(cpu_reg); + + if (cpu_mod == 3) + src = MMX_GETREG(cpu_rm); + else { SEG_CHECK_READ(cpu_state.ea_seg); src.l[0] = readmeml(easeg, cpu_state.eaaddr); src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].w[0] = ((int32_t) cpu_state.MM[cpu_reg].sw[0] * (int32_t) src.sw[0]) >> 16; - cpu_state.MM[cpu_reg].w[1] = ((int32_t) cpu_state.MM[cpu_reg].sw[1] * (int32_t) src.sw[1]) >> 16; - cpu_state.MM[cpu_reg].w[2] = ((int32_t) cpu_state.MM[cpu_reg].sw[2] * (int32_t) src.sw[2]) >> 16; - cpu_state.MM[cpu_reg].w[3] = ((int32_t) cpu_state.MM[cpu_reg].sw[3] * (int32_t) src.sw[3]) >> 16; - CLOCK_CYCLES(2); + CLOCK_CYCLES(1); } + dst->w[0] = ((int32_t) dst->sw[0] * (int32_t) src.sw[0]) >> 16; + dst->w[1] = ((int32_t) dst->sw[1] * (int32_t) src.sw[1]) >> 16; + dst->w[2] = ((int32_t) dst->sw[2] * (int32_t) src.sw[2]) >> 16; + dst->w[3] = ((int32_t) dst->sw[3] * (int32_t) src.sw[3]) >> 16; + CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_reg); + return 0; } @@ -410,19 +518,25 @@ static int opPSUBB_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] -= src.b[0]; - cpu_state.MM[cpu_reg].b[1] -= src.b[1]; - cpu_state.MM[cpu_reg].b[2] -= src.b[2]; - cpu_state.MM[cpu_reg].b[3] -= src.b[3]; - cpu_state.MM[cpu_reg].b[4] -= src.b[4]; - cpu_state.MM[cpu_reg].b[5] -= src.b[5]; - cpu_state.MM[cpu_reg].b[6] -= src.b[6]; - cpu_state.MM[cpu_reg].b[7] -= src.b[7]; + dst->b[0] -= src.b[0]; + dst->b[1] -= src.b[1]; + dst->b[2] -= src.b[2]; + dst->b[3] -= src.b[3]; + dst->b[4] -= src.b[4]; + dst->b[5] -= src.b[5]; + dst->b[6] -= src.b[6]; + dst->b[7] -= src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -430,19 +544,25 @@ static int opPSUBB_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] -= src.b[0]; - cpu_state.MM[cpu_reg].b[1] -= src.b[1]; - cpu_state.MM[cpu_reg].b[2] -= src.b[2]; - cpu_state.MM[cpu_reg].b[3] -= src.b[3]; - cpu_state.MM[cpu_reg].b[4] -= src.b[4]; - cpu_state.MM[cpu_reg].b[5] -= src.b[5]; - cpu_state.MM[cpu_reg].b[6] -= src.b[6]; - cpu_state.MM[cpu_reg].b[7] -= src.b[7]; + dst->b[0] -= src.b[0]; + dst->b[1] -= src.b[1]; + dst->b[2] -= src.b[2]; + dst->b[3] -= src.b[3]; + dst->b[4] -= src.b[4]; + dst->b[5] -= src.b[5]; + dst->b[6] -= src.b[6]; + dst->b[7] -= src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -451,15 +571,21 @@ static int opPSUBW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] -= src.w[0]; - cpu_state.MM[cpu_reg].w[1] -= src.w[1]; - cpu_state.MM[cpu_reg].w[2] -= src.w[2]; - cpu_state.MM[cpu_reg].w[3] -= src.w[3]; + dst->w[0] -= src.w[0]; + dst->w[1] -= src.w[1]; + dst->w[2] -= src.w[2]; + dst->w[3] -= src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -467,15 +593,21 @@ static int opPSUBW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] -= src.w[0]; - cpu_state.MM[cpu_reg].w[1] -= src.w[1]; - cpu_state.MM[cpu_reg].w[2] -= src.w[2]; - cpu_state.MM[cpu_reg].w[3] -= src.w[3]; + dst->w[0] -= src.w[0]; + dst->w[1] -= src.w[1]; + dst->w[2] -= src.w[2]; + dst->w[3] -= src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -484,13 +616,19 @@ static int opPSUBD_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] -= src.l[0]; - cpu_state.MM[cpu_reg].l[1] -= src.l[1]; + dst->l[0] -= src.l[0]; + dst->l[1] -= src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -498,13 +636,19 @@ static int opPSUBD_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] -= src.l[0]; - cpu_state.MM[cpu_reg].l[1] -= src.l[1]; + dst->l[0] -= src.l[0]; + dst->l[1] -= src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -513,20 +657,25 @@ static int opPSUBSB_a16(uint32_t fetchdat) { MMX_REG src; - pclog("opPSUBSB_a16(%08X)\n", fetchdat); + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]); + dst->sb[0] = SSATB(dst->sb[0] - src.sb[0]); + dst->sb[1] = SSATB(dst->sb[1] - src.sb[1]); + dst->sb[2] = SSATB(dst->sb[2] - src.sb[2]); + dst->sb[3] = SSATB(dst->sb[3] - src.sb[3]); + dst->sb[4] = SSATB(dst->sb[4] - src.sb[4]); + dst->sb[5] = SSATB(dst->sb[5] - src.sb[5]); + dst->sb[6] = SSATB(dst->sb[6] - src.sb[6]); + dst->sb[7] = SSATB(dst->sb[7] - src.sb[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -534,20 +683,25 @@ static int opPSUBSB_a32(uint32_t fetchdat) { MMX_REG src; - pclog("opPSUBSB_a32(%08X)\n", fetchdat); + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]); + dst->sb[0] = SSATB(dst->sb[0] - src.sb[0]); + dst->sb[1] = SSATB(dst->sb[1] - src.sb[1]); + dst->sb[2] = SSATB(dst->sb[2] - src.sb[2]); + dst->sb[3] = SSATB(dst->sb[3] - src.sb[3]); + dst->sb[4] = SSATB(dst->sb[4] - src.sb[4]); + dst->sb[5] = SSATB(dst->sb[5] - src.sb[5]); + dst->sb[6] = SSATB(dst->sb[6] - src.sb[6]); + dst->sb[7] = SSATB(dst->sb[7] - src.sb[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -556,19 +710,25 @@ static int opPSUBUSB_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]); - cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]); - cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]); - cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]); + dst->b[0] = USATB(dst->b[0] - src.b[0]); + dst->b[1] = USATB(dst->b[1] - src.b[1]); + dst->b[2] = USATB(dst->b[2] - src.b[2]); + dst->b[3] = USATB(dst->b[3] - src.b[3]); + dst->b[4] = USATB(dst->b[4] - src.b[4]); + dst->b[5] = USATB(dst->b[5] - src.b[5]); + dst->b[6] = USATB(dst->b[6] - src.b[6]); + dst->b[7] = USATB(dst->b[7] - src.b[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -576,19 +736,25 @@ static int opPSUBUSB_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]); - cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]); - cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]); - cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]); + dst->b[0] = USATB(dst->b[0] - src.b[0]); + dst->b[1] = USATB(dst->b[1] - src.b[1]); + dst->b[2] = USATB(dst->b[2] - src.b[2]); + dst->b[3] = USATB(dst->b[3] - src.b[3]); + dst->b[4] = USATB(dst->b[4] - src.b[4]); + dst->b[5] = USATB(dst->b[5] - src.b[5]); + dst->b[6] = USATB(dst->b[6] - src.b[6]); + dst->b[7] = USATB(dst->b[7] - src.b[7]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -597,15 +763,21 @@ static int opPSUBSW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]); + dst->sw[0] = SSATW(dst->sw[0] - src.sw[0]); + dst->sw[1] = SSATW(dst->sw[1] - src.sw[1]); + dst->sw[2] = SSATW(dst->sw[2] - src.sw[2]); + dst->sw[3] = SSATW(dst->sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -613,15 +785,21 @@ static int opPSUBSW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]); + dst->sw[0] = SSATW(dst->sw[0] - src.sw[0]); + dst->sw[1] = SSATW(dst->sw[1] - src.sw[1]); + dst->sw[2] = SSATW(dst->sw[2] - src.sw[2]); + dst->sw[3] = SSATW(dst->sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -630,15 +808,21 @@ static int opPSUBUSW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]); - cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]); - cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]); - cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]); + dst->w[0] = USATW(dst->w[0] - src.w[0]); + dst->w[1] = USATW(dst->w[1] - src.w[1]); + dst->w[2] = USATW(dst->w[2] - src.w[2]); + dst->w[3] = USATW(dst->w[3] - src.w[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -646,15 +830,21 @@ static int opPSUBUSW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]); - cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]); - cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]); - cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]); + dst->w[0] = USATW(dst->w[0] - src.w[0]); + dst->w[1] = USATW(dst->w[1] - src.w[1]); + dst->w[2] = USATW(dst->w[2] - src.w[2]); + dst->w[3] = USATW(dst->w[3] - src.w[3]); + + MMX_SETEXP(cpu_reg); return 0; } diff --git a/src/cpu/x86_ops_mmx_cmp.h b/src/cpu/x86_ops_mmx_cmp.h index 40ae66a9c..b3081b8e8 100644 --- a/src/cpu/x86_ops_mmx_cmp.h +++ b/src/cpu/x86_ops_mmx_cmp.h @@ -2,20 +2,25 @@ static int opPCMPEQB_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] == src.b[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0; + dst->b[0] = (dst->b[0] == src.b[0]) ? 0xff : 0; + dst->b[1] = (dst->b[1] == src.b[1]) ? 0xff : 0; + dst->b[2] = (dst->b[2] == src.b[2]) ? 0xff : 0; + dst->b[3] = (dst->b[3] == src.b[3]) ? 0xff : 0; + dst->b[4] = (dst->b[4] == src.b[4]) ? 0xff : 0; + dst->b[5] = (dst->b[5] == src.b[5]) ? 0xff : 0; + dst->b[6] = (dst->b[6] == src.b[6]) ? 0xff : 0; + dst->b[7] = (dst->b[7] == src.b[7]) ? 0xff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -23,20 +28,25 @@ static int opPCMPEQB_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] == src.b[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0; + dst->b[0] = (dst->b[0] == src.b[0]) ? 0xff : 0; + dst->b[1] = (dst->b[1] == src.b[1]) ? 0xff : 0; + dst->b[2] = (dst->b[2] == src.b[2]) ? 0xff : 0; + dst->b[3] = (dst->b[3] == src.b[3]) ? 0xff : 0; + dst->b[4] = (dst->b[4] == src.b[4]) ? 0xff : 0; + dst->b[5] = (dst->b[5] == src.b[5]) ? 0xff : 0; + dst->b[6] = (dst->b[6] == src.b[6]) ? 0xff : 0; + dst->b[7] = (dst->b[7] == src.b[7]) ? 0xff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -45,20 +55,25 @@ static int opPCMPGTB_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].sb[0] > src.sb[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0; + dst->b[0] = (dst->sb[0] > src.sb[0]) ? 0xff : 0; + dst->b[1] = (dst->sb[1] > src.sb[1]) ? 0xff : 0; + dst->b[2] = (dst->sb[2] > src.sb[2]) ? 0xff : 0; + dst->b[3] = (dst->sb[3] > src.sb[3]) ? 0xff : 0; + dst->b[4] = (dst->sb[4] > src.sb[4]) ? 0xff : 0; + dst->b[5] = (dst->sb[5] > src.sb[5]) ? 0xff : 0; + dst->b[6] = (dst->sb[6] > src.sb[6]) ? 0xff : 0; + dst->b[7] = (dst->sb[7] > src.sb[7]) ? 0xff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -66,20 +81,25 @@ static int opPCMPGTB_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].sb[0] > src.sb[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0; + dst->b[0] = (dst->sb[0] > src.sb[0]) ? 0xff : 0; + dst->b[1] = (dst->sb[1] > src.sb[1]) ? 0xff : 0; + dst->b[2] = (dst->sb[2] > src.sb[2]) ? 0xff : 0; + dst->b[3] = (dst->sb[3] > src.sb[3]) ? 0xff : 0; + dst->b[4] = (dst->sb[4] > src.sb[4]) ? 0xff : 0; + dst->b[5] = (dst->sb[5] > src.sb[5]) ? 0xff : 0; + dst->b[6] = (dst->sb[6] > src.sb[6]) ? 0xff : 0; + dst->b[7] = (dst->sb[7] > src.sb[7]) ? 0xff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -88,16 +108,21 @@ static int opPCMPEQW_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].w[0] == src.w[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0; + dst->w[0] = (dst->w[0] == src.w[0]) ? 0xffff : 0; + dst->w[1] = (dst->w[1] == src.w[1]) ? 0xffff : 0; + dst->w[2] = (dst->w[2] == src.w[2]) ? 0xffff : 0; + dst->w[3] = (dst->w[3] == src.w[3]) ? 0xffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -105,16 +130,21 @@ static int opPCMPEQW_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].w[0] == src.w[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0; + dst->w[0] = (dst->w[0] == src.w[0]) ? 0xffff : 0; + dst->w[1] = (dst->w[1] == src.w[1]) ? 0xffff : 0; + dst->w[2] = (dst->w[2] == src.w[2]) ? 0xffff : 0; + dst->w[3] = (dst->w[3] == src.w[3]) ? 0xffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -123,16 +153,21 @@ static int opPCMPGTW_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].sw[0] > src.sw[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0; + dst->w[0] = (dst->sw[0] > src.sw[0]) ? 0xffff : 0; + dst->w[1] = (dst->sw[1] > src.sw[1]) ? 0xffff : 0; + dst->w[2] = (dst->sw[2] > src.sw[2]) ? 0xffff : 0; + dst->w[3] = (dst->sw[3] > src.sw[3]) ? 0xffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -140,16 +175,21 @@ static int opPCMPGTW_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].sw[0] > src.sw[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0; + dst->w[0] = (dst->sw[0] > src.sw[0]) ? 0xffff : 0; + dst->w[1] = (dst->sw[1] > src.sw[1]) ? 0xffff : 0; + dst->w[2] = (dst->sw[2] > src.sw[2]) ? 0xffff : 0; + dst->w[3] = (dst->sw[3] > src.sw[3]) ? 0xffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -158,14 +198,19 @@ static int opPCMPEQD_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].l[0] == src.l[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->l[0] == src.l[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->l[1] == src.l[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -173,14 +218,19 @@ static int opPCMPEQD_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].l[0] == src.l[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->l[0] == src.l[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->l[1] == src.l[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -189,14 +239,19 @@ static int opPCMPGTD_a16(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].sl[0] > src.sl[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->sl[0] > src.sl[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->sl[1] > src.sl[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } @@ -204,14 +259,19 @@ static int opPCMPGTD_a32(uint32_t fetchdat) { MMX_REG src; - + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].sl[0] > src.sl[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0; + dst->l[0] = (dst->sl[0] > src.sl[0]) ? 0xffffffff : 0; + dst->l[1] = (dst->sl[1] > src.sl[1]) ? 0xffffffff : 0; + + MMX_SETEXP(cpu_reg); return 0; } diff --git a/src/cpu/x86_ops_mmx_logic.h b/src/cpu/x86_ops_mmx_logic.h index c22c820c1..26d7c1693 100644 --- a/src/cpu/x86_ops_mmx_logic.h +++ b/src/cpu/x86_ops_mmx_logic.h @@ -2,24 +2,38 @@ static int opPAND_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q &= src.q; + dst->q &= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } static int opPAND_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q &= src.q; + dst->q &= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } @@ -27,24 +41,38 @@ static int opPANDN_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; + dst->q = ~dst->q & src.q; + + MMX_SETEXP(cpu_reg); + return 0; } static int opPANDN_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; + dst->q = ~dst->q & src.q; + + MMX_SETEXP(cpu_reg); + return 0; } @@ -52,24 +80,38 @@ static int opPOR_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q |= src.q; + dst->q |= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } static int opPOR_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q |= src.q; + dst->q |= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } @@ -77,23 +119,37 @@ static int opPXOR_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q ^= src.q; + dst->q ^= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } static int opPXOR_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].q ^= src.q; + dst->q ^= src.q; + + MMX_SETEXP(cpu_reg); + return 0; } diff --git a/src/cpu/x86_ops_mmx_mov.h b/src/cpu/x86_ops_mmx_mov.h index bb51573e6..65bbb0c01 100644 --- a/src/cpu/x86_ops_mmx_mov.h +++ b/src/cpu/x86_ops_mmx_mov.h @@ -1,88 +1,112 @@ static int opMOVD_l_mm_a16(uint32_t fetchdat) { + uint32_t dst; + MMX_REG *op; MMX_ENTER(); fetch_ea_16(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l; - cpu_state.MM[cpu_reg].l[1] = 0; + op->l[0] = cpu_state.regs[cpu_rm].l; + op->l[1] = 0; CLOCK_CYCLES(1); } else { - uint32_t dst; - SEG_CHECK_READ(cpu_state.ea_seg); dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - cpu_state.MM[cpu_reg].l[0] = dst; - cpu_state.MM[cpu_reg].l[1] = 0; + op->l[0] = dst; + op->l[1] = 0; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } static int opMOVD_l_mm_a32(uint32_t fetchdat) { + uint32_t dst; + MMX_REG *op; MMX_ENTER(); fetch_ea_32(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l; - cpu_state.MM[cpu_reg].l[1] = 0; + op->l[0] = cpu_state.regs[cpu_rm].l; + op->l[1] = 0; CLOCK_CYCLES(1); } else { - uint32_t dst; - SEG_CHECK_READ(cpu_state.ea_seg); dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - cpu_state.MM[cpu_reg].l[0] = dst; - cpu_state.MM[cpu_reg].l[1] = 0; + op->l[0] = dst; + op->l[1] = 0; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } static int opMOVD_mm_l_a16(uint32_t fetchdat) { + MMX_REG *op; MMX_ENTER(); fetch_ea_16(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + cpu_state.regs[cpu_rm].l = op->l[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); + writememl(easeg, cpu_state.eaaddr, op->l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } static int opMOVD_mm_l_a32(uint32_t fetchdat) { + MMX_REG *op; MMX_ENTER(); fetch_ea_32(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + cpu_state.regs[cpu_rm].l = op->l[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); + writememl(easeg, cpu_state.eaaddr, op->l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } @@ -91,45 +115,59 @@ opMOVD_mm_l_a32(uint32_t fetchdat) static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) { + MMX_REG *op; + if (in_smm) return opSMINT(fetchdat); MMX_ENTER(); fetch_ea_16(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + cpu_state.regs[cpu_rm].l = op->l[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); + writememl(easeg, cpu_state.eaaddr, op->l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } static int opMOVD_mm_l_a32_cx(uint32_t fetchdat) { + MMX_REG *op; + if (in_smm) return opSMINT(fetchdat); MMX_ENTER(); fetch_ea_32(fetchdat); + + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + cpu_state.regs[cpu_rm].l = op->l[0]; CLOCK_CYCLES(1); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); - writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); + writememl(easeg, cpu_state.eaaddr, op->l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } #endif @@ -137,81 +175,121 @@ opMOVD_mm_l_a32_cx(uint32_t fetchdat) static int opMOVQ_q_mm_a16(uint32_t fetchdat) { + uint64_t dst; + MMX_REG src; + MMX_REG *op; MMX_ENTER(); fetch_ea_16(fetchdat); + + src = MMX_GETREG(cpu_rm); + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q; + op->q = src.q; CLOCK_CYCLES(1); } else { - uint64_t dst; - SEG_CHECK_READ(cpu_state.ea_seg); dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - cpu_state.MM[cpu_reg].q = dst; + + op->q = dst; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } static int opMOVQ_q_mm_a32(uint32_t fetchdat) { + uint64_t dst; + MMX_REG src; + MMX_REG *op; MMX_ENTER(); fetch_ea_32(fetchdat); + + src = MMX_GETREG(cpu_rm); + op = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q; + op->q = src.q; CLOCK_CYCLES(1); } else { - uint64_t dst; - SEG_CHECK_READ(cpu_state.ea_seg); dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; - cpu_state.MM[cpu_reg].q = dst; + + op->q = dst; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } static int opMOVQ_mm_q_a16(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); fetch_ea_16(fetchdat); + + src = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_rm); + if (cpu_mod == 3) { - cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q; + dst->q = src.q; CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_rm); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); - writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); + writememq(easeg, cpu_state.eaaddr, src.q); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } static int opMOVQ_mm_q_a32(uint32_t fetchdat) { + MMX_REG src; + MMX_REG *dst; + MMX_ENTER(); fetch_ea_32(fetchdat); + + src = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_rm); + if (cpu_mod == 3) { - cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q; + dst->q = src.q; CLOCK_CYCLES(1); + + MMX_SETEXP(cpu_rm); } else { SEG_CHECK_WRITE(cpu_state.ea_seg); CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); - writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); + writememq(easeg, cpu_state.eaaddr, src.q); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); } + return 0; } diff --git a/src/cpu/x86_ops_mmx_pack.h b/src/cpu/x86_ops_mmx_pack.h index f0180db91..90590638b 100644 --- a/src/cpu/x86_ops_mmx_pack.h +++ b/src/cpu/x86_ops_mmx_pack.h @@ -1,45 +1,61 @@ static int opPUNPCKLDQ_a16(uint32_t fetchdat) { + uint32_t usrc; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + src = MMX_GETREG(cpu_rm); + dst = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0]; + dst->l[1] = src.l[0]; CLOCK_CYCLES(1); } else { - uint32_t src; - SEG_CHECK_READ(cpu_state.ea_seg); - src = readmeml(easeg, cpu_state.eaaddr); + usrc = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].l[1] = src; + dst->l[1] = usrc; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } static int opPUNPCKLDQ_a32(uint32_t fetchdat) { + uint32_t usrc; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + src = MMX_GETREG(cpu_rm); + dst = MMX_GETREGP(cpu_reg); + if (cpu_mod == 3) { - cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0]; + dst->l[1] = src.l[0]; CLOCK_CYCLES(1); } else { - uint32_t src; - SEG_CHECK_READ(cpu_state.ea_seg); - src = readmeml(easeg, cpu_state.eaaddr); + usrc = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; - cpu_state.MM[cpu_reg].l[1] = src; + dst->l[1] = usrc; CLOCK_CYCLES(2); } + + MMX_SETEXP(cpu_reg); + return 0; } @@ -47,13 +63,19 @@ static int opPUNPCKHDQ_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1]; - cpu_state.MM[cpu_reg].l[1] = src.l[1]; + dst->l[0] = dst->l[1]; + dst->l[1] = src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -61,13 +83,19 @@ static int opPUNPCKHDQ_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1]; - cpu_state.MM[cpu_reg].l[1] = src.l[1]; + dst->l[0] = dst->l[1]; + dst->l[1] = src.l[1]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -76,19 +104,25 @@ static int opPUNPCKLBW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[7] = src.b[3]; - cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3]; - cpu_state.MM[cpu_reg].b[5] = src.b[2]; - cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2]; - cpu_state.MM[cpu_reg].b[3] = src.b[1]; - cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1]; - cpu_state.MM[cpu_reg].b[1] = src.b[0]; - cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0]; + dst->b[7] = src.b[3]; + dst->b[6] = dst->b[3]; + dst->b[5] = src.b[2]; + dst->b[4] = dst->b[2]; + dst->b[3] = src.b[1]; + dst->b[2] = dst->b[1]; + dst->b[1] = src.b[0]; + dst->b[0] = dst->b[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -96,19 +130,25 @@ static int opPUNPCKLBW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[7] = src.b[3]; - cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3]; - cpu_state.MM[cpu_reg].b[5] = src.b[2]; - cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2]; - cpu_state.MM[cpu_reg].b[3] = src.b[1]; - cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1]; - cpu_state.MM[cpu_reg].b[1] = src.b[0]; - cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0]; + dst->b[7] = src.b[3]; + dst->b[6] = dst->b[3]; + dst->b[5] = src.b[2]; + dst->b[4] = dst->b[2]; + dst->b[3] = src.b[1]; + dst->b[2] = dst->b[1]; + dst->b[1] = src.b[0]; + dst->b[0] = dst->b[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -117,19 +157,25 @@ static int opPUNPCKHBW_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4]; - cpu_state.MM[cpu_reg].b[1] = src.b[4]; - cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5]; - cpu_state.MM[cpu_reg].b[3] = src.b[5]; - cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6]; - cpu_state.MM[cpu_reg].b[5] = src.b[6]; - cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7]; - cpu_state.MM[cpu_reg].b[7] = src.b[7]; + dst->b[0] = dst->b[4]; + dst->b[1] = src.b[4]; + dst->b[2] = dst->b[5]; + dst->b[3] = src.b[5]; + dst->b[4] = dst->b[6]; + dst->b[5] = src.b[6]; + dst->b[6] = dst->b[7]; + dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -137,19 +183,25 @@ static int opPUNPCKHBW_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4]; - cpu_state.MM[cpu_reg].b[1] = src.b[4]; - cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5]; - cpu_state.MM[cpu_reg].b[3] = src.b[5]; - cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6]; - cpu_state.MM[cpu_reg].b[5] = src.b[6]; - cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7]; - cpu_state.MM[cpu_reg].b[7] = src.b[7]; + dst->b[0] = dst->b[4]; + dst->b[1] = src.b[4]; + dst->b[2] = dst->b[5]; + dst->b[3] = src.b[5]; + dst->b[4] = dst->b[6]; + dst->b[5] = src.b[6]; + dst->b[6] = dst->b[7]; + dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -158,15 +210,21 @@ static int opPUNPCKLWD_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[3] = src.w[1]; - cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1]; - cpu_state.MM[cpu_reg].w[1] = src.w[0]; - cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0]; + dst->w[3] = src.w[1]; + dst->w[2] = dst->w[1]; + dst->w[1] = src.w[0]; + dst->w[0] = dst->w[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -174,15 +232,21 @@ static int opPUNPCKLWD_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[3] = src.w[1]; - cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1]; - cpu_state.MM[cpu_reg].w[1] = src.w[0]; - cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0]; + dst->w[3] = src.w[1]; + dst->w[2] = dst->w[1]; + dst->w[1] = src.w[0]; + dst->w[0] = dst->w[0]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -191,15 +255,21 @@ static int opPUNPCKHWD_a16(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2]; - cpu_state.MM[cpu_reg].w[1] = src.w[2]; - cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3]; - cpu_state.MM[cpu_reg].w[3] = src.w[3]; + dst->w[0] = dst->w[2]; + dst->w[1] = src.w[2]; + dst->w[2] = dst->w[3]; + dst->w[3] = src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -207,15 +277,21 @@ static int opPUNPCKHWD_a32(uint32_t fetchdat) { MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSRC(); - cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2]; - cpu_state.MM[cpu_reg].w[1] = src.w[2]; - cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3]; - cpu_state.MM[cpu_reg].w[3] = src.w[3]; + dst->w[0] = dst->w[2]; + dst->w[1] = src.w[2]; + dst->w[2] = dst->w[3]; + dst->w[3] = src.w[3]; + + MMX_SETEXP(cpu_reg); return 0; } @@ -223,42 +299,52 @@ opPUNPCKHWD_a32(uint32_t fetchdat) static int opPACKSSWB_a16(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]); + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->sb[0] = SSATB(dst->sw[0]); + dst->sb[1] = SSATB(dst->sw[1]); + dst->sb[2] = SSATB(dst->sw[2]); + dst->sb[3] = SSATB(dst->sw[3]); + dst->sb[4] = SSATB(src.sw[0]); + dst->sb[5] = SSATB(src.sw[1]); + dst->sb[6] = SSATB(src.sw[2]); + dst->sb[7] = SSATB(src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } static int opPACKSSWB_a32(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]); - cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]); - cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]); - cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]); - cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]); - cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]); - cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]); - cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]); + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->sb[0] = SSATB(dst->sw[0]); + dst->sb[1] = SSATB(dst->sw[1]); + dst->sb[2] = SSATB(dst->sw[2]); + dst->sb[3] = SSATB(dst->sw[3]); + dst->sb[4] = SSATB(src.sw[0]); + dst->sb[5] = SSATB(src.sw[1]); + dst->sb[6] = SSATB(src.sw[2]); + dst->sb[7] = SSATB(src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -266,42 +352,52 @@ opPACKSSWB_a32(uint32_t fetchdat) static int opPACKUSWB_a16(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_16(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]); - cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]); - cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]); - cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]); + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->sw[0]); + dst->b[1] = USATB(dst->sw[1]); + dst->b[2] = USATB(dst->sw[2]); + dst->b[3] = USATB(dst->sw[3]); + dst->b[4] = USATB(src.sw[0]); + dst->b[5] = USATB(src.sw[1]); + dst->b[6] = USATB(src.sw[2]); + dst->b[7] = USATB(src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } static int opPACKUSWB_a32(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; MMX_ENTER(); fetch_ea_32(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]); - cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]); - cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]); - cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]); - cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]); - cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]); - cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]); - cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]); + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->sw[0]); + dst->b[1] = USATB(dst->sw[1]); + dst->b[2] = USATB(dst->sw[2]); + dst->b[3] = USATB(dst->sw[3]); + dst->b[4] = USATB(src.sw[0]); + dst->b[5] = USATB(src.sw[1]); + dst->b[6] = USATB(src.sw[2]); + dst->b[7] = USATB(src.sw[3]); + + MMX_SETEXP(cpu_reg); return 0; } @@ -309,34 +405,48 @@ opPACKUSWB_a32(uint32_t fetchdat) static int opPACKSSDW_a16(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; + MMX_REG dst2; MMX_ENTER(); fetch_ea_16(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]); + dst = MMX_GETREGP(cpu_reg); + dst2 = *dst; + + MMX_GETSRC(); + + dst->sw[0] = SSATW(dst2.sl[0]); + dst->sw[1] = SSATW(dst2.sl[1]); + dst->sw[2] = SSATW(src.sl[0]); + dst->sw[3] = SSATW(src.sl[1]); + + MMX_SETEXP(cpu_reg); return 0; } static int opPACKSSDW_a32(uint32_t fetchdat) { - MMX_REG src, dst; + MMX_REG src; + MMX_REG *dst; + MMX_REG dst2; MMX_ENTER(); fetch_ea_32(fetchdat); - MMX_GETSRC(); - dst = cpu_state.MM[cpu_reg]; - cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]); - cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]); - cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]); - cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]); + dst = MMX_GETREGP(cpu_reg); + dst2 = *dst; + + MMX_GETSRC(); + + dst->sw[0] = SSATW(dst2.sl[0]); + dst->sw[1] = SSATW(dst2.sl[1]); + dst->sw[2] = SSATW(src.sl[0]); + dst->sw[3] = SSATW(src.sl[1]); + + MMX_SETEXP(cpu_reg); return 0; } diff --git a/src/cpu/x86_ops_mmx_shift.h b/src/cpu/x86_ops_mmx_shift.h index c9ddc9b93..c0c80e87e 100644 --- a/src/cpu/x86_ops_mmx_shift.h +++ b/src/cpu/x86_ops_mmx_shift.h @@ -1,6 +1,6 @@ #define MMX_GETSHIFT() \ if (cpu_mod == 3) { \ - shift = cpu_state.MM[cpu_rm].b[0]; \ + shift = (MMX_GETREG(cpu_rm)).b[0]; \ CLOCK_CYCLES(1); \ } else { \ SEG_CHECK_READ(cpu_state.ea_seg); \ @@ -16,37 +16,39 @@ opPSxxW_imm(uint32_t fetchdat) int reg = fetchdat & 7; int op = fetchdat & 0x38; int shift = (fetchdat >> 8) & 0xff; + MMX_REG *dst; cpu_state.pc += 2; MMX_ENTER(); + dst = MMX_GETREGP(reg); switch (op) { case 0x10: /*PSRLW*/ if (shift > 15) - cpu_state.MM[reg].q = 0; + dst->q = 0; else { - cpu_state.MM[reg].w[0] >>= shift; - cpu_state.MM[reg].w[1] >>= shift; - cpu_state.MM[reg].w[2] >>= shift; - cpu_state.MM[reg].w[3] >>= shift; + dst->w[0] >>= shift; + dst->w[1] >>= shift; + dst->w[2] >>= shift; + dst->w[3] >>= shift; } break; case 0x20: /*PSRAW*/ if (shift > 15) shift = 15; - cpu_state.MM[reg].sw[0] >>= shift; - cpu_state.MM[reg].sw[1] >>= shift; - cpu_state.MM[reg].sw[2] >>= shift; - cpu_state.MM[reg].sw[3] >>= shift; + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; break; case 0x30: /*PSLLW*/ if (shift > 15) - cpu_state.MM[reg].q = 0; + dst->q = 0; else { - cpu_state.MM[reg].w[0] <<= shift; - cpu_state.MM[reg].w[1] <<= shift; - cpu_state.MM[reg].w[2] <<= shift; - cpu_state.MM[reg].w[3] <<= shift; + dst->w[0] <<= shift; + dst->w[1] <<= shift; + dst->w[2] <<= shift; + dst->w[3] <<= shift; } break; default: @@ -55,6 +57,8 @@ opPSxxW_imm(uint32_t fetchdat) return 0; } + MMX_SETEXP(reg); + CLOCK_CYCLES(1); return 0; } @@ -62,126 +66,162 @@ opPSxxW_imm(uint32_t fetchdat) static int opPSLLW_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].w[0] <<= shift; - cpu_state.MM[cpu_reg].w[1] <<= shift; - cpu_state.MM[cpu_reg].w[2] <<= shift; - cpu_state.MM[cpu_reg].w[3] <<= shift; + dst->w[0] <<= shift; + dst->w[1] <<= shift; + dst->w[2] <<= shift; + dst->w[3] <<= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSLLW_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].w[0] <<= shift; - cpu_state.MM[cpu_reg].w[1] <<= shift; - cpu_state.MM[cpu_reg].w[2] <<= shift; - cpu_state.MM[cpu_reg].w[3] <<= shift; + dst->w[0] <<= shift; + dst->w[1] <<= shift; + dst->w[2] <<= shift; + dst->w[3] <<= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRLW_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].w[0] >>= shift; - cpu_state.MM[cpu_reg].w[1] >>= shift; - cpu_state.MM[cpu_reg].w[2] >>= shift; - cpu_state.MM[cpu_reg].w[3] >>= shift; + dst->w[0] >>= shift; + dst->w[1] >>= shift; + dst->w[2] >>= shift; + dst->w[3] >>= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRLW_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].w[0] >>= shift; - cpu_state.MM[cpu_reg].w[1] >>= shift; - cpu_state.MM[cpu_reg].w[2] >>= shift; - cpu_state.MM[cpu_reg].w[3] >>= shift; + dst->w[0] >>= shift; + dst->w[1] >>= shift; + dst->w[2] >>= shift; + dst->w[3] >>= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRAW_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) shift = 15; - cpu_state.MM[cpu_reg].sw[0] >>= shift; - cpu_state.MM[cpu_reg].sw[1] >>= shift; - cpu_state.MM[cpu_reg].sw[2] >>= shift; - cpu_state.MM[cpu_reg].sw[3] >>= shift; + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } static int opPSRAW_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 15) shift = 15; - cpu_state.MM[cpu_reg].sw[0] >>= shift; - cpu_state.MM[cpu_reg].sw[1] >>= shift; - cpu_state.MM[cpu_reg].sw[2] >>= shift; - cpu_state.MM[cpu_reg].sw[3] >>= shift; + dst->sw[0] >>= shift; + dst->sw[1] >>= shift; + dst->sw[2] >>= shift; + dst->sw[3] >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } @@ -192,31 +232,34 @@ opPSxxD_imm(uint32_t fetchdat) int reg = fetchdat & 7; int op = fetchdat & 0x38; int shift = (fetchdat >> 8) & 0xff; + MMX_REG *dst; cpu_state.pc += 2; MMX_ENTER(); + dst = MMX_GETREGP(reg); + switch (op) { case 0x10: /*PSRLD*/ if (shift > 31) - cpu_state.MM[reg].q = 0; + dst->q = 0; else { - cpu_state.MM[reg].l[0] >>= shift; - cpu_state.MM[reg].l[1] >>= shift; + dst->l[0] >>= shift; + dst->l[1] >>= shift; } break; case 0x20: /*PSRAD*/ if (shift > 31) shift = 31; - cpu_state.MM[reg].sl[0] >>= shift; - cpu_state.MM[reg].sl[1] >>= shift; + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; break; case 0x30: /*PSLLD*/ if (shift > 31) - cpu_state.MM[reg].q = 0; + dst->q = 0; else { - cpu_state.MM[reg].l[0] <<= shift; - cpu_state.MM[reg].l[1] <<= shift; + dst->l[0] <<= shift; + dst->l[1] <<= shift; } break; default: @@ -225,6 +268,8 @@ opPSxxD_imm(uint32_t fetchdat) return 0; } + MMX_SETEXP(reg); + CLOCK_CYCLES(1); return 0; } @@ -232,114 +277,150 @@ opPSxxD_imm(uint32_t fetchdat) static int opPSLLD_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].l[0] <<= shift; - cpu_state.MM[cpu_reg].l[1] <<= shift; + dst->l[0] <<= shift; + dst->l[1] <<= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSLLD_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].l[0] <<= shift; - cpu_state.MM[cpu_reg].l[1] <<= shift; + dst->l[0] <<= shift; + dst->l[1] <<= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRLD_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].l[0] >>= shift; - cpu_state.MM[cpu_reg].l[1] >>= shift; + dst->l[0] >>= shift; + dst->l[1] >>= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRLD_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else { - cpu_state.MM[cpu_reg].l[0] >>= shift; - cpu_state.MM[cpu_reg].l[1] >>= shift; + dst->l[0] >>= shift; + dst->l[1] >>= shift; } + MMX_SETEXP(cpu_reg); + return 0; } static int opPSRAD_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) shift = 31; - cpu_state.MM[cpu_reg].sl[0] >>= shift; - cpu_state.MM[cpu_reg].sl[1] >>= shift; + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } static int opPSRAD_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 31) shift = 31; - cpu_state.MM[cpu_reg].sl[0] >>= shift; - cpu_state.MM[cpu_reg].sl[1] >>= shift; + dst->sl[0] >>= shift; + dst->sl[1] >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } @@ -350,27 +431,32 @@ opPSxxQ_imm(uint32_t fetchdat) int reg = fetchdat & 7; int op = fetchdat & 0x38; int shift = (fetchdat >> 8) & 0xff; + MMX_REG *dst; cpu_state.pc += 2; + MMX_ENTER(); + dst = MMX_GETREGP(reg); + switch (op) { case 0x10: /*PSRLW*/ if (shift > 63) - cpu_state.MM[reg].q = 0; + dst->q = 0; else - cpu_state.MM[reg].q >>= shift; + dst->q >>= shift; break; case 0x20: /*PSRAW*/ if (shift > 63) shift = 63; - cpu_state.MM[reg].sq >>= shift; + + dst->sq >>= shift; break; case 0x30: /*PSLLW*/ if (shift > 63) - cpu_state.MM[reg].q = 0; + dst->q = 0; else - cpu_state.MM[reg].q <<= shift; + dst->q <<= shift; break; default: cpu_state.pc = cpu_state.oldpc; @@ -378,6 +464,8 @@ opPSxxQ_imm(uint32_t fetchdat) return 0; } + MMX_SETEXP(reg); + CLOCK_CYCLES(1); return 0; } @@ -385,34 +473,46 @@ opPSxxQ_imm(uint32_t fetchdat) static int opPSLLQ_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else - cpu_state.MM[cpu_reg].q <<= shift; + dst->q <<= shift; + + MMX_SETEXP(cpu_reg); return 0; } static int opPSLLQ_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else - cpu_state.MM[cpu_reg].q <<= shift; + dst->q <<= shift; + + MMX_SETEXP(cpu_reg); return 0; } @@ -420,34 +520,46 @@ opPSLLQ_a32(uint32_t fetchdat) static int opPSRLQ_a16(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else - cpu_state.MM[cpu_reg].q >>= shift; + dst->q >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } static int opPSRLQ_a32(uint32_t fetchdat) { + MMX_REG *dst; int shift; MMX_ENTER(); fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + MMX_GETSHIFT(); if (shift > 63) - cpu_state.MM[cpu_reg].q = 0; + dst->q = 0; else - cpu_state.MM[cpu_reg].q >>= shift; + dst->q >>= shift; + + MMX_SETEXP(cpu_reg); return 0; } diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 98ceb105b..181b7b9ca 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -439,6 +439,79 @@ FPU_tagof(const floatx80 reg) return X87_TAG_VALID; } +uint8_t +pack_FPU_TW(uint16_t twd) +{ + uint8_t tag_byte = 0; + + if ((twd & 0x0003) != 0x0003) tag_byte |= 0x01; + if ((twd & 0x000c) != 0x000c) tag_byte |= 0x02; + if ((twd & 0x0030) != 0x0030) tag_byte |= 0x04; + if ((twd & 0x00c0) != 0x00c0) tag_byte |= 0x08; + if ((twd & 0x0300) != 0x0300) tag_byte |= 0x10; + if ((twd & 0x0c00) != 0x0c00) tag_byte |= 0x20; + if ((twd & 0x3000) != 0x3000) tag_byte |= 0x40; + if ((twd & 0xc000) != 0xc000) tag_byte |= 0x80; + + return tag_byte; +} + +uint16_t +unpack_FPU_TW(uint16_t tag_byte) +{ + uint32_t twd = 0; + + /* FTW + * + * Note that the original format for FTW can be recreated from the stored + * FTW valid bits and the stored 80-bit FP data (assuming the stored data + * was not the contents of MMX registers) using the following table: + + | Exponent | Exponent | Fraction | J,M bits | FTW valid | x87 FTW | + | all 1s | all 0s | all 0s | | | | + ------------------------------------------------------------------- + | 0 | 0 | 0 | 0x | 1 | S 10 | + | 0 | 0 | 0 | 1x | 1 | V 00 | + ------------------------------------------------------------------- + | 0 | 0 | 1 | 00 | 1 | S 10 | + | 0 | 0 | 1 | 10 | 1 | V 00 | + ------------------------------------------------------------------- + | 0 | 1 | 0 | 0x | 1 | S 10 | + | 0 | 1 | 0 | 1x | 1 | S 10 | + ------------------------------------------------------------------- + | 0 | 1 | 1 | 00 | 1 | Z 01 | + | 0 | 1 | 1 | 10 | 1 | S 10 | + ------------------------------------------------------------------- + | 1 | 0 | 0 | 1x | 1 | S 10 | + | 1 | 0 | 0 | 1x | 1 | S 10 | + ------------------------------------------------------------------- + | 1 | 0 | 1 | 00 | 1 | S 10 | + | 1 | 0 | 1 | 10 | 1 | S 10 | + ------------------------------------------------------------------- + | all combinations above | 0 | E 11 | + + * + * The J-bit is defined to be the 1-bit binary integer to the left of + * the decimal place in the significand. + * + * The M-bit is defined to be the most significant bit of the fractional + * portion of the significand (i.e., the bit immediately to the right of + * the decimal place). When the M-bit is the most significant bit of the + * fractional portion of the significand, it must be 0 if the fraction + * is all 0's. + */ + + for (int index = 7; index >= 0; index--, twd <<= 2, tag_byte <<= 1) { + if (tag_byte & 0x80) { + const floatx80 *fpu_reg = &fpu_state.st_space[index & 7]; + twd |= FPU_tagof(*fpu_reg); + } else { + twd |= X87_TAG_EMPTY; + } + } + + return (twd >> 2); +} #ifdef ENABLE_808X_LOG void diff --git a/src/cpu/x87.h b/src/cpu/x87.h index 5d460bc4b..66d51dbd9 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -10,9 +10,14 @@ static __inline void x87_set_mmx(void) { uint64_t *p; - cpu_state.TOP = 0; - p = (uint64_t *) cpu_state.tag; - *p = 0x0101010101010101ull; + if (fpu_softfloat) { + fpu_state.tag = 0; + fpu_state.tos = 0; /* reset FPU Top-Of-Stack */ + } else { + cpu_state.TOP = 0; + p = (uint64_t *) cpu_state.tag; + *p = 0x0101010101010101ull; + } cpu_state.ismmx = 1; } @@ -20,8 +25,13 @@ static __inline void x87_emms(void) { uint64_t *p; - p = (uint64_t *) cpu_state.tag; - *p = 0; + if (fpu_softfloat) { + fpu_state.tag = 0xffff; + fpu_state.tos = 0; /* reset FPU Top-Of-Stack */ + } else { + p = (uint64_t *) cpu_state.tag; + *p = 0; + } cpu_state.ismmx = 0; } @@ -141,6 +151,8 @@ void FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack); int FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status); int FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status); int FPU_tagof(const floatx80 reg); +uint8_t pack_FPU_TW(uint16_t twd); +uint16_t unpack_FPU_TW(uint16_t tag_byte); static __inline uint16_t i387_get_control_word(void) diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 37ccf3555..ee5a6d17e 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -82,7 +82,8 @@ #define KBC_VEN_NCR 0x24 #define KBC_VEN_ALI 0x28 #define KBC_VEN_SIEMENS 0x2c -#define KBC_VEN_MASK 0x3c +#define KBC_VEN_COMPAQ 0x30 +#define KBC_VEN_MASK 0x7c #define FLAG_CLOCK 0x01 #define FLAG_CACHE 0x02 @@ -981,6 +982,8 @@ write64_generic(void *priv, uint8_t val) } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) /* (B0 or F0) | (0x08 or 0x0c) */ kbc_delay_to_ob(dev, ((dev->p1 | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00); + else if (kbc_ven == KBC_VEN_COMPAQ) + kbc_delay_to_ob(dev, dev->p1 | (hasfpu ? 0x00 : 0x04), 0, 0x00); else /* (B0 or F0) | (0x04 or 0x44) */ kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00); @@ -1968,6 +1971,7 @@ kbc_at_init(const device_t *info) case KBC_VEN_GENERIC: case KBC_VEN_NCR: case KBC_VEN_IBM_PS1: + case KBC_VEN_COMPAQ: dev->write64_ven = write64_generic; break; @@ -2141,6 +2145,20 @@ const device_t keyboard_at_ncr_device = { .config = NULL }; +const device_t keyboard_at_compaq_device = { + .name = "PC/AT Keyboard (Compaq)", + .internal_name = "keyboard_at_compaq", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_COMPAQ, + .init = kbc_at_init, + .close = kbc_at_close, + .reset = kbc_at_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t keyboard_ps2_device = { .name = "PS/2 Keyboard", .internal_name = "keyboard_ps2", diff --git a/src/device/serial_passthrough.c b/src/device/serial_passthrough.c index a8c531f07..b703cd67c 100644 --- a/src/device/serial_passthrough.c +++ b/src/device/serial_passthrough.c @@ -119,6 +119,8 @@ static void serial_passthrough_speed_changed(void *priv) { serial_passthrough_t *dev = (serial_passthrough_t *) priv; + if (!dev) + return; timer_stop(&dev->host_to_serial_timer); /* FIXME: do something to dev->baudrate */ @@ -132,9 +134,11 @@ static void serial_passthrough_dev_close(void *priv) { serial_passthrough_t *dev = (serial_passthrough_t *) priv; + if (!dev) + return; /* Detach passthrough device from COM port */ - if (dev && dev->serial && dev->serial->sd) + if (dev->serial && dev->serial->sd) memset(dev->serial->sd, 0, sizeof(serial_device_t)); plat_serpt_close(dev); @@ -184,6 +188,10 @@ serial_passthrough_dev_init(const device_t *info) /* Attach passthrough device to a COM port */ dev->serial = serial_attach_ex(dev->port, serial_passthrough_rcr_cb, serial_passthrough_write, serial_passthrough_transmit_period, serial_passthrough_lcr_callback, dev); + if (!dev->serial) { + free(dev); + return NULL; + } strncpy(dev->host_serial_path, device_get_config_string("host_serial_path"), 1023); #ifdef _WIN32 diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 589f04292..9d5232cdf 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -668,8 +668,8 @@ img_load(int drive, char *fn) uint16_t track_bytes = 0; uint8_t *literal; img_t *dev; - int temp_rate; - int guess = 0; + int temp_rate = 0; + int guess = 0; int size; ext = path_get_extension(fn); diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 392539c73..f09507601 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -234,6 +234,7 @@ extern const device_t keyboard_at_tg_ami_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_at_olivetti_device; extern const device_t keyboard_at_ncr_device; +extern const device_t keyboard_at_compaq_device; extern const device_t keyboard_ps2_device; extern const device_t keyboard_ps2_ps1_device; extern const device_t keyboard_ps2_ps1_pci_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fc0cfd873..c64dbe60d 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -556,9 +556,8 @@ extern int machine_at_cmdpc_init(const machine_t *); extern int machine_at_portableii_init(const machine_t *); extern int machine_at_portableiii_init(const machine_t *); extern int machine_at_portableiii386_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) extern int machine_at_deskpro386_init(const machine_t *); -#endif +extern int machine_at_deskpro386_01_1988_init(const machine_t *); /* m_at_socket4.c */ extern void machine_at_premiere_common_init(const machine_t *, int); diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index e6510e3f1..b21da9fba 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -24,6 +24,8 @@ typedef struct ibm8514_t { int force_old_addr; int type; + int local; + int bpp; uint32_t vram_size; uint32_t vram_mask; @@ -32,6 +34,7 @@ typedef struct ibm8514_t { uint8_t dac_mask, dac_status; uint32_t *map8; int dac_addr, dac_pos, dac_r, dac_g; + int internal_pitch; struct { uint16_t subsys_cntl; @@ -58,7 +61,7 @@ typedef struct ibm8514_t { uint8_t pix_trans[2]; int poly_draw; int ssv_state; - int x1, x2, y1, y2; + int16_t x1, x2, x3, y1, y2; int sys_cnt, sys_cnt2; int temp_cnt; int16_t cx, cy, oldcy; @@ -80,6 +83,7 @@ typedef struct ibm8514_t { uint16_t scratch; int fill_state, xdir, ydir; + uint32_t ge_offset; } accel; uint16_t test; @@ -90,7 +94,7 @@ typedef struct ibm8514_t { dispon, hdisp_on, linecountff, vc, linepos, oddeven, cursoron, blink, scrollcache, firstline, lastline, firstline_draw, lastline_draw, - displine, fullchange, x_add, y_add; + displine, fullchange; uint32_t ma, maback; uint8_t *vram, *changedvram, linedbl; @@ -103,11 +107,13 @@ typedef struct ibm8514_t { int disp_cntl, interlace; uint8_t subsys_cntl, subsys_stat; - volatile int force_busy, force_busy2; + atomic_int force_busy, force_busy2; int blitter_busy; uint64_t blitter_time; uint64_t status_time; int pitch; + int ext_pitch; + int ext_crt_pitch; } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_eeprom.h b/src/include/86box/vid_ati_eeprom.h index 1fa083eaa..7de5170d8 100644 --- a/src/include/86box/vid_ati_eeprom.h +++ b/src/include/86box/vid_ati_eeprom.h @@ -43,6 +43,7 @@ typedef struct ati_eeprom_t { } ati_eeprom_t; void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type); +void ati_eeprom_load_mach8(ati_eeprom_t *eeprom, char *fn); void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat); int ati_eeprom_read(ati_eeprom_t *eeprom); diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 93fb9f17c..f8dafdd20 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -31,8 +31,9 @@ # define FLAG_NOSKEW 16 # define FLAG_ADDR_BY16 32 # define FLAG_RAMDAC_SHIFT 64 -# define FLAG_128K_MASK 128 - +# define FLAG_ATI 128 +# define FLAG_S3_911_16BIT 256 +# define FLAG_512K_MASK 512 struct monitor_t; typedef struct { diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index 069718b9f..550ae7cd6 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -36,6 +36,7 @@ typedef struct xga_t { mem_mapping_t linear_mapping; mem_mapping_t video_mapping; rom_t bios_rom; + rom_t vga_bios_rom; xga_hwcursor_t hwcursor, hwcursor_latch; PALETTE extpal; @@ -57,7 +58,7 @@ typedef struct xga_t { uint8_t clk_sel_1, clk_sel_2; uint8_t hwc_control; uint8_t bus_arb; - uint8_t select_pos_isa; + uint8_t isa_pos_enable; uint8_t hwcursor_oddeven; uint8_t cfg_reg_instance; uint8_t rowcount; @@ -70,6 +71,8 @@ typedef struct xga_t { uint8_t sprite_data[1024]; uint8_t scrollcache; uint8_t direct_color; + uint8_t dma_channel; + uint8_t instance_isa, instance_num, ext_mem_addr; uint8_t *vram, *changedvram; int16_t hwc_pos_x; diff --git a/src/include/86box/vid_xga_device.h b/src/include/86box/vid_xga_device.h index a92c6d3c6..7aa274d30 100644 --- a/src/include/86box/vid_xga_device.h +++ b/src/include/86box/vid_xga_device.h @@ -17,6 +17,11 @@ #ifndef VIDEO_XGA_DEVICE_H #define VIDEO_XGA_DEVICE_H +extern int xga_has_vga; + +#ifdef EMU_DEVICE_H extern const device_t xga_device; extern const device_t xga_isa_device; +extern const device_t inmos_isa_device; +#endif #endif /*VIDEO_XGA_DEVICE_H*/ diff --git a/src/include/86box/video.h b/src/include/86box/video.h index fb7800685..b915fe35d 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -60,8 +60,10 @@ enum { #define VIDEO_FLAG_TYPE_CGA 0 #define VIDEO_FLAG_TYPE_MDA 1 #define VIDEO_FLAG_TYPE_SPECIAL 2 -#define VIDEO_FLAG_TYPE_NONE 3 -#define VIDEO_FLAG_TYPE_MASK 3 +#define VIDEO_FLAG_TYPE_8514 3 +#define VIDEO_FLAG_TYPE_XGA 4 +#define VIDEO_FLAG_TYPE_NONE 5 +#define VIDEO_FLAG_TYPE_MASK 7 typedef struct video_timings_t { int type; @@ -206,6 +208,7 @@ extern double cpuclock; extern int emu_fps; extern int frames; extern int readflash; +extern int ibm8514_has_vga; /* Function handler pointers. */ extern void (*video_recalctimings)(void); @@ -232,6 +235,8 @@ extern int video_card_get_flags(int card); extern int video_is_mda(void); extern int video_is_cga(void); extern int video_is_ega_vga(void); +extern int video_is_8514(void); +extern int video_is_xga(void); extern void video_inform_monitor(int type, const video_timings_t *ptr, int monitor_index); extern int video_get_type_monitor(int monitor_index); @@ -290,8 +295,12 @@ extern uint32_t video_color_transform(uint32_t color); /* IBM XGA */ extern void xga_device_add(void); -/* IBM 8514/A and generic clones*/ +/* IBM 8514/A and clones*/ extern void ibm8514_device_add(void); +extern const device_t mach8_isa_device; +extern const device_t mach32_isa_device; +extern const device_t mach32_vlb_device; +extern const device_t mach32_pci_device; /* ATi Mach64 */ extern const device_t mach64gx_isa_device; diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index dd8370a4f..3676a9d92 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -31,6 +31,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> +#include <86box/keyboard.h> #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> @@ -41,22 +42,28 @@ #include <86box/vid_cga.h> #include <86box/vid_cga_comp.h> + +static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; + enum { COMPAQ_PORTABLEII = 0, COMPAQ_PORTABLEIII, COMPAQ_PORTABLEIII386, - COMPAQ_DESKPRO386 + COMPAQ_DESKPRO386, + COMPAQ_DESKPRO386_01_1988 }; #define CGA_RGB 0 #define CGA_COMPOSITE 1 -#define COMPOSITE_OLD 0 -#define COMPOSITE_NEW 1 - /*Very rough estimate*/ #define VID_CLOCK (double) (651 * 416 * 60) +static uint8_t cga_crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* Mapping of attributes to colours */ static uint32_t amber; static uint32_t black; @@ -72,6 +79,8 @@ static uint32_t normcols[256][2]; */ static int8_t cpq_st_display_internal = -1; +static uint8_t mdaattr[256][2][2]; + static void compaq_plasma_display_set(uint8_t internal) { @@ -85,21 +94,13 @@ compaq_plasma_display_get(void) } typedef struct compaq_plasma_t { - mem_mapping_t plasma_mapping; cga_t cga; uint8_t port_23c6; uint8_t internal_monitor; - uint8_t attrmap; /* Attribute mapping register */ - int linepos, displine; - uint8_t *vram; - uint64_t dispontime, dispofftime; - int dispon, fullchange; + uint8_t attrmap; } compaq_plasma_t; -static uint8_t cga_crtcmask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +static int compaq_machine_type = 0; /* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */ static mem_mapping_t ram_mapping; @@ -121,8 +122,18 @@ compaq_plasma_recalctimings(compaq_plasma_t *self) disptime = 651; _dispontime = 640; _dispofftime = disptime - _dispontime; - self->dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); - self->dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); + self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32)); +} + +static void +compaq_plasma_waitstates(void *p) +{ + int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 }; + int ws; + + ws = ws_array[cycles & 0xf]; + sub_cycles(ws); } static void @@ -130,7 +141,8 @@ compaq_plasma_write(uint32_t addr, uint8_t val, void *priv) { compaq_plasma_t *self = (compaq_plasma_t *) priv; - self->vram[addr & 0x7fff] = val; + self->cga.vram[addr & 0x7fff] = val; + compaq_plasma_waitstates(&self->cga); } static uint8_t @@ -139,206 +151,12 @@ compaq_plasma_read(uint32_t addr, void *priv) compaq_plasma_t *self = (compaq_plasma_t *) priv; uint8_t ret; - ret = (self->vram[addr & 0x7fff]); + compaq_plasma_waitstates(&self->cga); + ret = (self->cga.vram[addr & 0x7fff]); return ret; } -/* Draw a row of text in 80-column mode */ -static void -compaq_plasma_text80(compaq_plasma_t *self) -{ - uint32_t cols[2]; - int c; - uint8_t chr; - uint8_t attr; - int drawcursor; - int cursorline; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff; - - sc = (self->displine) & 15; - addr = ((ma & ~1) + (self->displine >> 4) * 80) * 2; - ma += (self->displine >> 4) * 80; - - if ((self->cga.crtc[10] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[10] & 0x0F) * 2 <= sc) && ((self->cga.crtc[11] & 0x0F) * 2 >= sc); - - for (uint8_t x = 0; x < 80; x++) { - chr = self->vram[(addr + 2 * x) & 0x7FFF]; - attr = self->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - - if (self->cga.cgamode & 0x20) { /* Blink */ - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) - cols[1] = cols[0]; - } else { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - ((uint32_t *) buffer32->line[self->displine])[(x << 3) + c] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } else { - for (c = 0; c < 8; c++) - ((uint32_t *) buffer32->line[self->displine])[(x << 3) + c] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } -} - -/* Draw a row of text in 40-column mode */ -static void -compaq_plasma_text40(compaq_plasma_t *self) -{ - uint32_t cols[2]; - int c; - uint8_t chr; - uint8_t attr; - int drawcursor; - int cursorline; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff; - - sc = (self->displine) & 15; - addr = ((ma & ~1) + (self->displine >> 4) * 40) * 2; - ma += (self->displine >> 4) * 40; - - if ((self->cga.crtc[10] & 0x60) == 0x20) - cursorline = 0; - else - cursorline = ((self->cga.crtc[10] & 0x0F) * 2 <= sc) && ((self->cga.crtc[11] & 0x0F) * 2 >= sc); - - for (uint8_t x = 0; x < 40; x++) { - chr = self->vram[(addr + 2 * x) & 0x7FFF]; - attr = self->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 8) && (self->cga.cgablink & 16)); - - blink = ((self->cga.cgablink & 16) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - - if (self->cga.cgamode & 0x20) { /* Blink */ - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) - cols[1] = cols[0]; - } else { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) { - for (c = 0; c < 8; c++) { - ((uint32_t *) buffer32->line[self->displine])[(x << 4) + c * 2] = ((uint32_t *) buffer32->line[self->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } else { - for (c = 0; c < 8; c++) { - ((uint32_t *) buffer32->line[self->displine])[(x << 4) + c * 2] = ((uint32_t *) buffer32->line[self->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } -} - -/* Draw a line in CGA 640x200 or Compaq Plasma 640x400 mode */ -static void -compaq_plasma_cgaline6(compaq_plasma_t *self) -{ - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (self->cga.cgacol & 0x0F) ? amber : black; - uint32_t bg = black; - - uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; - - if ((self->cga.crtc[9] == 3) || (self->port_23c6 & 1)) /* 640*400 */ { - addr = ((self->displine) & 1) * 0x2000 + ((self->displine >> 1) & 1) * 0x4000 + (self->displine >> 2) * 80 + ((ma & ~1) << 1); - } else { - addr = ((self->displine >> 1) & 1) * 0x2000 + (self->displine >> 2) * 80 + ((ma & ~1) << 1); - } - for (uint8_t x = 0; x < 80; x++) { - dat = self->vram[addr & 0x7FFF]; - addr++; - - for (uint8_t c = 0; c < 8; c++) { - ink = (dat & 0x80) ? fg : bg; - if (!(self->cga.cgamode & 8)) - ink = black; - ((uint32_t *) buffer32->line[self->displine])[x * 8 + c] = ink; - dat <<= 1; - } - } -} - -/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to - * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ -static void -compaq_plasma_cgaline4(compaq_plasma_t *self) -{ - uint8_t dat; - uint8_t pattern; - uint32_t ink0 = 0; - uint32_t ink1 = 0; - uint16_t addr; - - uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; - - /* 320*200 */ - addr = ((self->displine >> 1) & 1) * 0x2000 + (self->displine >> 2) * 80 + ((ma & ~1) << 1); - - for (uint8_t x = 0; x < 80; x++) { - dat = self->vram[addr & 0x7FFF]; - addr++; - - for (uint8_t c = 0; c < 4; c++) { - pattern = (dat & 0xC0) >> 6; - if (!(self->cga.cgamode & 8)) - pattern = 0; - - switch (pattern & 3) { - case 0: - ink0 = ink1 = black; - break; - case 1: - if (self->displine & 1) { - ink0 = black; - ink1 = black; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 2: - if (self->displine & 1) { - ink0 = black; - ink1 = amber; - } else { - ink0 = amber; - ink1 = black; - } - break; - case 3: - ink0 = ink1 = amber; - break; - } - ((uint32_t *) buffer32->line[self->displine])[x * 8 + 2 * c] = ink0; - ((uint32_t *) buffer32->line[self->displine])[x * 8 + 2 * c + 1] = ink1; - dat <<= 2; - } - } -} - static void compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) { @@ -348,7 +166,7 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) switch (addr) { /* Emulated CRTC, register select */ case 0x3d4: - self->cga.crtcreg = val & 31; + cga_out(addr, val, &self->cga); break; /* Emulated CRTC, value */ @@ -366,33 +184,26 @@ compaq_plasma_out(uint16_t addr, uint8_t val, void *priv) if (old != val) { if (self->cga.crtcreg < 0xe || self->cga.crtcreg > 0x10) { - self->fullchange = changeframecount; + self->cga.fullchange = changeframecount; compaq_plasma_recalctimings(self); } } break; - case 0x3d8: - self->cga.cgamode = val; - break; - case 0x3d9: - self->cga.cgacol = val; + cga_out(addr, val, &self->cga); break; case 0x13c6: - if (val & 8) - compaq_plasma_display_set(1); - else - compaq_plasma_display_set(0); + compaq_plasma_display_set((val & 8) ? 1 : 0); break; case 0x23c6: self->port_23c6 = val; if (val & 8) /* Disable internal CGA */ - mem_mapping_disable(&self->plasma_mapping); + mem_mapping_disable(&self->cga.mapping); else - mem_mapping_enable(&self->plasma_mapping); + mem_mapping_enable(&self->cga.mapping); break; } } @@ -405,31 +216,38 @@ compaq_plasma_in(uint16_t addr, void *priv) switch (addr) { case 0x3d4: - ret = self->cga.crtcreg; + case 0x3da: + ret = cga_in(addr, &self->cga); break; case 0x3d5: if (self->cga.crtcreg == 0x12) { - ret = self->attrmap & 0x0F; + ret = self->attrmap & 0x0f; if (self->internal_monitor) ret |= 0x30; /* Plasma / CRT */ } else - ret = self->cga.crtc[self->cga.crtcreg]; - break; - - case 0x3da: - ret = self->cga.cgastat; + ret = cga_in(addr, &self->cga); break; case 0x13c6: - if (compaq_plasma_display_get()) - ret = 8; - else - ret = 0; + ret = compaq_plasma_display_get() ? 8 : 0; + ret |= 4; + break; + + case 0x1bc6: + ret = 0; + if (compaq_plasma_display_get()) { + if ((self->cga.cgamode & 0x12) == 0x12) { + if (self->port_23c6 & 8) + ret |= 0x40; + else + ret |= 0x20; + } + } break; case 0x23c6: - ret = self->port_23c6; + ret = 0; break; } @@ -440,56 +258,242 @@ static void compaq_plasma_poll(void *p) { compaq_plasma_t *self = (compaq_plasma_t *) p; + uint8_t chr, attr; + uint8_t sc; + uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff; + uint16_t addr; + int drawcursor; + int x, c; + int cursorline; + int blink = 0; + int underline = 0; + uint32_t ink = 0; + uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black; + uint32_t bg = black; + uint32_t cols[2]; + uint8_t dat2, pattern; + uint32_t ink0 = 0, ink1 = 0; /* Switch between internal plasma and external CRT display. */ - if (cpq_st_display_internal != -1 && cpq_st_display_internal != self->internal_monitor) { + if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) { self->internal_monitor = cpq_st_display_internal; compaq_plasma_recalctimings(self); } + /* graphic mode and not mode 40h */ if (!self->internal_monitor && !(self->port_23c6 & 1)) { cga_poll(&self->cga); return; } - if (!self->linepos) { - timer_advance_u64(&self->cga.timer, self->dispofftime); + /* mode 40h or text mode */ + if (!self->cga.linepos) { + timer_advance_u64(&self->cga.timer, self->cga.dispofftime); self->cga.cgastat |= 1; - self->linepos = 1; - if (self->dispon) { - if (self->displine == 0) + self->cga.linepos = 1; + if (self->cga.cgadispon) { + if (self->cga.displine == 0) { video_wait_for_buffer(); + } + if (self->cga.cgamode & 2) { + if (self->cga.cgamode & 0x10) { + /* 640x400 mode */ + if (self->port_23c6 & 1) /* 640*400 */ { + addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + } + for (x = 0; x < 80; x++) { + dat2 = self->cga.vram[(addr & 0x7FFF)]; + addr++; - /* Graphics */ - if (self->cga.cgamode & 0x02) { - if (self->cga.cgamode & 0x10) - compaq_plasma_cgaline6(self); + for (c = 0; c < 8; c++) { + ink = (dat2 & 0x80) ? fg : bg; + if (!(self->cga.cgamode & 8)) + ink = black; + ((uint32_t *) buffer32->line[self->cga.displine])[x * 8 + c] = ink; + dat2 <<= 1; + } + } + } else { + addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1); + for (x = 0; x < 80; x++) { + dat2 = self->cga.vram[(addr & 0x7fff)]; + addr++; + + for (c = 0; c < 4; c++) { + pattern = (dat2 & 0xC0) >> 6; + if (!(self->cga.cgamode & 8)) + pattern = 0; + + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; + break; + case 1: + if (self->cga.displine & 1) { + ink0 = black; + ink1 = black; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 2: + if (self->cga.displine & 1) { + ink0 = black; + ink1 = amber; + } else { + ink0 = amber; + ink1 = black; + } + break; + case 3: + ink0 = ink1 = amber; + break; + } + buffer32->line[self->cga.displine][x * 8 + 2 * c] = ink0; + buffer32->line[self->cga.displine][x * 8 + 2 * c + 1] = ink1; + dat2 <<= 2; + } + } + } + } else if (self->cga.cgamode & 1) { + /* 80-col */ + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) * 2; + ma += (self->cga.displine >> 4) * 80; + + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; else - compaq_plasma_cgaline4(self); - } else if (self->cga.cgamode & 0x01) /* High-res text */ - compaq_plasma_text80(self); - else - compaq_plasma_text40(self); + cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + + /* for each text column */ + for (x = 0; x < 80; x++) { + /* video output enabled */ + if (self->cga.cgamode & 8) { + chr = self->cga.vram[(addr + 2 * x) & 0x7fff]; + attr = self->cga.vram[(addr + 2 * x + 1) & 0x7fff]; + } else + chr = attr = 0; + /* check if cursor has to be drawn */ + drawcursor = ((ma == ca) && cursorline && self->cga.cursoron); + underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); + if (underline) { + /* set forecolor to white */ + attr |= 7; + } + blink = 0; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = (attr & 0x80) * 8 + 7 + 16; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } else { + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 3) + c] = cols[(fontdatm[chr + self->cga.fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + + ++ma; + } + } else { /* 40-col */ + sc = self->cga.displine & 0x0f; + addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) * 2; + ma += (self->cga.displine >> 4) * 40; + + if ((self->cga.crtc[0x0a] & 0x60) == 0x20) + cursorline = 0; + else + cursorline = ((self->cga.crtc[0x0a] & 0x0f) * 2 <= sc) && ((self->cga.crtc[0x0b] & 0x0F) * 2 >= sc); + + for (x = 0; x < 40; x++) { + if (self->cga.cgamode & 8) { + chr = self->cga.vram[(addr + 2 * x) & 0x7fff]; + attr = self->cga.vram[(addr + 2 * x + 1) & 0x7fff]; + } else { + chr = attr = 0; + } + drawcursor = ((ma == ca) && cursorline && self->cga.cursoron); + underline = ((self->port_23c6 & 0x40) && (attr & 0x1) && !(attr & 0x6)); + if (underline) { + /* set forecolor to white */ + attr |= 7; + } + blink = 0; + /* blink active */ + if (self->cga.cgamode & 0x20) { + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + /* attribute 7 active and not cursor */ + if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) { + /* set blinking */ + cols[1] = cols[0]; + blink = 1; + } + } else { + /* Set intensity bit */ + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; + blink = (attr & 0x80) * 8 + 7 + 16; + } + /* character underline active and 7th row of pixels in character height being drawn */ + if (underline && (sc == 7)) { + /* for each pixel in character width */ + for (c = 0; c < 8; c++) + buffer32->line[self->cga.displine][(x << 4) + (c * 2)] = buffer32->line[self->cga.displine][(x << 4) + (c * 2) + 1] = mdaattr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } + } else { + for (c = 0; c < 8; c++) { + buffer32->line[self->cga.displine][(x << 4) + c * 2] = buffer32->line[self->cga.displine][(x << 4) + c * 2 + 1] = cols[(fontdatm[chr][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; + } + } } - self->displine++; + self->cga.displine++; /* Hardcode a fixed refresh rate and VSYNC timing */ - if (self->displine == 400) { /* Start of VSYNC */ + if (self->cga.displine == 400) { /* Start of VSYNC */ self->cga.cgastat |= 8; - self->dispon = 0; + self->cga.cgadispon = 0; } - if (self->displine == 416) { /* End of VSYNC */ - self->displine = 0; + if (self->cga.displine == 416) { /* End of VSYNC */ + self->cga.displine = 0; self->cga.cgastat &= ~8; - self->dispon = 1; + self->cga.cgadispon = 1; } } else { - if (self->dispon) + if (self->cga.cgadispon) self->cga.cgastat &= ~1; - timer_advance_u64(&self->cga.timer, self->dispontime); - self->linepos = 0; + timer_advance_u64(&self->cga.timer, self->cga.dispontime); + self->cga.linepos = 0; - if (self->displine == 400) { + if (self->cga.displine == 400) { /* Hardcode 640x400 window size */ if ((640 != xsize) || (400 != ysize) || video_force_resize_get()) { xsize = 640; @@ -515,14 +519,41 @@ compaq_plasma_poll(void *p) video_bpp = 1; else video_bpp = 2; - } else video_bpp = 0; + self->cga.cgablink++; } } } +static void +compaq_plasma_mdaattr_rebuild(void) +{ + int c; + + for (c = 0; c < 256; c++) { + mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; + if (c & 8) + mdaattr[c][0][1] = 15 + 16; + else + mdaattr[c][0][1] = 7 + 16; + } + + mdaattr[0x70][0][1] = 16; + mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; + mdaattr[0xF0][0][1] = 16; + mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; + mdaattr[0x78][0][1] = 16 + 7; + mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; + mdaattr[0xF8][0][1] = 16 + 7; + mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; + mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; + mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; + mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; + mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; +} + static void compaq_plasma_recalcattrs(compaq_plasma_t *self) { @@ -537,10 +568,10 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) * are bold */ /* Set up colours */ - amber = makecol(0xff, 0x7D, 0x00); - black = makecol(0x64, 0x19, 0x00); + amber = makecol(0xff, 0x7d, 0x00); + black = makecol(0x64, 0x0c, 0x00); - /* Initialise the attribute mapping. Start by defaulting everything + /* Initialize the attribute mapping. Start by defaulting everything * to black on amber, and with bold set by bit 3 */ for (n = 0; n < 256; n++) { blinkcols[n][0] = normcols[n][0] = amber; @@ -607,36 +638,37 @@ compaq_plasma_recalcattrs(compaq_plasma_t *self) static void * compaq_plasma_init(const device_t *info) { - int display_type; compaq_plasma_t *self = malloc(sizeof(compaq_plasma_t)); memset(self, 0, sizeof(compaq_plasma_t)); - display_type = device_get_config_int("display_type"); - self->cga.composite = (display_type != CGA_RGB); - self->cga.revision = device_get_config_int("composite_type"); + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma); + loadfont_ex("roms/machines/portableiii/K Combined.bin", 1, 0x4bb2); - self->vram = malloc(0x8000); + self->cga.composite = 0; + self->cga.revision = 0; + + self->cga.vram = malloc(0x8000); self->internal_monitor = 1; cga_comp_init(self->cga.revision); timer_add(&self->cga.timer, compaq_plasma_poll, self, 1); - mem_mapping_add(&self->plasma_mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); + mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, compaq_plasma_read, NULL, NULL, compaq_plasma_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self); io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x13c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); + io_sethandler(0x1bc6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); io_sethandler(0x23c6, 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self); /* Default attribute mapping is 4 */ self->attrmap = 4; compaq_plasma_recalcattrs(self); - self->cga.cgastat = 0xF4; - self->cga.vram = self->vram; - + self->cga.cgastat = 0xf4; overscan_x = overscan_y = 16; self->cga.rgb_type = device_get_config_int("rgb_type"); cga_palette = (self->cga.rgb_type << 1); cgapal_rebuild(); + compaq_plasma_mdaattr_rebuild(); return self; } @@ -646,8 +678,7 @@ compaq_plasma_close(void *p) { compaq_plasma_t *self = (compaq_plasma_t *) p; - free(self->vram); - + free(self->cga.vram); free(self); } @@ -661,38 +692,10 @@ compaq_plasma_speed_changed(void *p) const device_config_t compaq_plasma_config[] = { // clang-format off - { - .name = "display_type", - .description = "Display type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = CGA_RGB, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "RGB", .value = CGA_RGB }, - { .description = "Composite", .value = CGA_COMPOSITE }, - { .description = "" } - } - }, - { - .name = "composite_type", - .description = "Composite type", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = COMPOSITE_OLD, - .file_filter = "", - .spinner = { 0 }, - { - { .description = "Old", .value = COMPOSITE_OLD }, - { .description = "New", .value = COMPOSITE_NEW }, - { .description = "" } - } - }, { .name = "rgb_type", - .description = "RGB type", - .type = CONFIG_SELECTION, + .description = "RGB type", + .type = CONFIG_SELECTION, .default_string = "", .default_int = 0, .file_filter = "", @@ -702,7 +705,6 @@ const device_config_t compaq_plasma_config[] = { { .description = "Green Monochrome", .value = 1 }, { .description = "Amber Monochrome", .value = 2 }, { .description = "Gray Monochrome", .value = 3 }, - { .description = "Color (no brown)", .value = 4 }, { .description = "" } } }, @@ -781,26 +783,36 @@ write_raml(uint32_t addr, uint32_t val, void *priv) static void machine_at_compaq_init(const machine_t *model, int type) { - if (type != COMPAQ_DESKPRO386) + compaq_machine_type = type; + + if ((type != COMPAQ_DESKPRO386) && (type != COMPAQ_DESKPRO386_01_1988)) mem_remap_top(384); if (fdc_type == FDC_INTERNAL) device_add(&fdc_at_device); - mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, - read_ram, read_ramw, read_raml, - write_ram, write_ramw, write_raml, - 0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL); + if ((type == COMPAQ_DESKPRO386) || (type == COMPAQ_DESKPRO386_01_1988) || (type == COMPAQ_PORTABLEIII386)) + mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, + read_ram, read_ramw, read_raml, + write_ram, write_ramw, write_raml, + 0xa0000 + ram, MEM_MAPPING_EXTERNAL, NULL); + else + mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, + read_ram, read_ramw, read_raml, + write_ram, write_ramw, write_raml, + 0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL); video_reset(gfxcard[0]); switch (type) { case COMPAQ_PORTABLEII: + machine_at_init(model); break; case COMPAQ_PORTABLEIII: if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); + machine_at_init(model); break; case COMPAQ_PORTABLEIII386: @@ -808,15 +820,17 @@ machine_at_compaq_init(const machine_t *model, int type) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); + machine_at_init(model); break; case COMPAQ_DESKPRO386: + case COMPAQ_DESKPRO386_01_1988: if (hdc_current == 1) device_add(&ide_isa_device); + machine_at_common_init(model); + device_add(&keyboard_at_compaq_device); break; } - - machine_at_init(model); } int @@ -841,9 +855,9 @@ machine_at_portableiii_init(const machine_t *model) { int ret; - ret = bios_load_interleavedr("roms/machines/portableiii/Compaq Portable III - BIOS - 106779-002 - Even.bin", - "roms/machines/portableiii/Compaq Portable III - BIOS - 106778-002 - Odd.bin", - 0x000f8000, 65536, 0); + ret = bios_load_linearr("roms/machines/portableiii/K Combined.bin", + 0x000f8000, 65536, 0); + if (bios_only || !ret) return ret; @@ -858,9 +872,8 @@ machine_at_portableiii386_init(const machine_t *model) { int ret; - ret = bios_load_interleavedr("roms/machines/portableiii/Compaq Portable III - BIOS - 106779-002 - Even.bin", - "roms/machines/portableiii/Compaq Portable III - BIOS - 106778-002 - Odd.bin", - 0x000f8000, 65536, 0); + ret = bios_load_linearr("roms/machines/portableiii/K Combined.bin", + 0x000f8000, 65536, 0); if (bios_only || !ret) return ret; @@ -870,14 +883,13 @@ machine_at_portableiii386_init(const machine_t *model) return ret; } -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) int machine_at_deskpro386_init(const machine_t *model) { int ret; ret = bios_load_linearr("roms/machines/deskpro386/1986-09-04-HI.json.bin", - 0x000fc000, 65536, 0); + 0x000f8000, 65536, 0); if (bios_only || !ret) return ret; @@ -886,4 +898,19 @@ machine_at_deskpro386_init(const machine_t *model) return ret; } -#endif + +int +machine_at_deskpro386_01_1988_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linearr("roms/machines/deskpro386/1988-01-28.json.bin", + 0x000f8000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_compaq_init(model, COMPAQ_DESKPRO386_01_1988); + + return ret; +} diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index 3cedb669a..f13fe72cd 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -200,8 +200,8 @@ machine_at_p2bls_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* SCSI */ - pci_register_slot(0x07, PCI_CARD_NORMAL, 3, 4, 1, 2); /* LAN */ + pci_register_slot(0x06, PCI_CARD_SCSI, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NETWORK, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e92ad21d2..f7a78bb95 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2587,8 +2587,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 6000000, - .max_bus = 8000000, + .min_bus = 0, + .max_bus = 0, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2904,8 +2904,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 6000000, - .max_bus = 8000000, + .min_bus = 0, + .max_bus = 0, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -2943,8 +2943,8 @@ const machine_t machines[] = { .cpu = { .package = CPU_PKG_286, .block = CPU_BLOCK_NONE, - .min_bus = 6000000, - .max_bus = 8000000, + .min_bus = 0, + .max_bus = 0, .min_voltage = 0, .max_voltage = 0, .min_multi = 0, @@ -4670,9 +4670,8 @@ const machine_t machines[] = { .net_device = NULL }, /* Uses Compaq KBC firmware. */ -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) { - .name = "[ISA] Compaq Deskpro 386", + .name = "[ISA] Compaq Deskpro 386 (September 1986)", .internal_name = "deskpro386", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_DISCRETE, @@ -4692,13 +4691,51 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_APM, + .flags = MACHINE_IDE, .ram = { - .min = 1024, - .max = 14336, - .step = 1024 + .min = 640, + .max = 16384, + .step = 128 }, - .nvrmask = 127, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0, + .gpio = 0, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + { + .name = "[ISA] Compaq Deskpro 386 (January 1988)", + .internal_name = "deskpro386_01_1988", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_deskpro386_01_1988_init, + .pad = 0, + .pad0 = 0, + .pad1 = MACHINE_AVAILABLE, + .pad2 = 0, + .cpu = { + .package = CPU_PKG_386DX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_IDE, + .ram = { + .min = 640, + .max = 16384, + .step = 128 + }, + .nvrmask = 63, .kbc_device = NULL, .kbc_p1 = 0, .gpio = 0, @@ -4709,7 +4746,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_DESKPRO386) */ { .name = "[ISA] Compaq Portable III (386)", .internal_name = "portableiii386", @@ -4731,7 +4767,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, + .flags = MACHINE_IDE | MACHINE_VIDEO, .ram = { .min = 1024, .max = 14336, diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index c774258e2..dea0c7fbe 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -20,4 +20,15 @@ if(APPLE) if (NOT GHOSTSCRIPT_LIB) message(WARNING "Could not find ghostscript. The library will not be bundled and any related features will not work.") endif() -endif () \ No newline at end of file +endif() + +find_package(PkgConfig REQUIRED) +pkg_check_modules(FREETYPE REQUIRED IMPORTED_TARGET freetype2) +target_link_libraries(86Box PkgConfig::FREETYPE) +if(STATIC_BUILD) + if(QT) + # Qt provides its own version of harfbuzz which leads to duplicated symbols. + target_link_options(86Box PRIVATE "LINKER:--allow-multiple-definition") + endif() + target_link_libraries(86Box -static ${FREETYPE_STATIC_LIBRARIES}) +endif() diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 5fc3646bc..b4099bc63 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -65,7 +65,6 @@ #include <86box/pit.h> #include <86box/path.h> #include <86box/plat.h> -#include <86box/plat_dynld.h> #include <86box/ui.h> #include <86box/lpt.h> #include <86box/video.h> @@ -85,45 +84,8 @@ #define PAGE_CPI 10.0 /* standard 10 cpi */ #define PAGE_LPI 6.0 /* standard 6 lpi */ -#ifdef _WIN32 -# define PATH_FREETYPE_DLL "freetype.dll" -#elif defined __APPLE__ -# define PATH_FREETYPE_DLL "libfreetype.6.dylib" -#else -# define PATH_FREETYPE_DLL "libfreetype.so.6" -#endif - /* FreeType library handles - global so they can be shared. */ -FT_Library ft_lib = NULL; -void *ft_handle = NULL; - -static int (*ft_Init_FreeType)(FT_Library *alibrary); -static int (*ft_Done_Face)(FT_Face face); -static int (*ft_New_Face)(FT_Library library, const char *filepathname, - FT_Long face_index, FT_Face *aface); -static int (*ft_Set_Char_Size)(FT_Face face, FT_F26Dot6 char_width, - FT_F26Dot6 char_height, - FT_UInt horz_resolution, - FT_UInt vert_resolution); -static int (*ft_Set_Transform)(FT_Face face, FT_Matrix *matrix, - FT_Vector *delta); -static int (*ft_Get_Char_Index)(FT_Face face, FT_ULong charcode); -static int (*ft_Load_Glyph)(FT_Face face, FT_UInt glyph_index, - FT_Int32 load_flags); -static int (*ft_Render_Glyph)(FT_GlyphSlot slot, - FT_Render_Mode render_mode); - -static dllimp_t ft_imports[] = { - {"FT_Init_FreeType", &ft_Init_FreeType }, - { "FT_New_Face", &ft_New_Face }, - { "FT_Done_Face", &ft_Done_Face }, - { "FT_Set_Char_Size", &ft_Set_Char_Size }, - { "FT_Set_Transform", &ft_Set_Transform }, - { "FT_Get_Char_Index", &ft_Get_Char_Index}, - { "FT_Load_Glyph", &ft_Load_Glyph }, - { "FT_Render_Glyph", &ft_Render_Glyph }, - { NULL, NULL } -}; +FT_Library ft_lib = NULL; /* The fonts. */ #define FONT_DEFAULT 0 @@ -544,7 +506,7 @@ update_font(escp_t *dev) /* Release current font if we have one. */ if (dev->fontface) - ft_Done_Face(dev->fontface); + FT_Done_Face(dev->fontface); if (dev->print_quality == QUALITY_DRAFT) fn = FONT_FILE_DOTMATRIX; @@ -580,7 +542,7 @@ update_font(escp_t *dev) escp_log("Temp file=%s\n", path); /* Load the new font. */ - if (ft_New_Face(ft_lib, path, 0, &dev->fontface)) { + if (FT_New_Face(ft_lib, path, 0, &dev->fontface)) { escp_log("ESC/P: unable to load font '%s'\n", path); dev->fontface = NULL; } @@ -626,7 +588,7 @@ update_font(escp_t *dev) dev->actual_cpi /= 2.0 / 3.0; } - ft_Set_Char_Size(dev->fontface, + FT_Set_Char_Size(dev->fontface, (uint16_t) (hpoints * 64), (uint16_t) (vpoints * 64), dev->dpi, dev->dpi); @@ -636,7 +598,7 @@ update_font(escp_t *dev) matrix.xy = (FT_Fixed) (0.20 * 0x10000L); matrix.yx = 0; matrix.yy = 0x10000L; - ft_Set_Transform(dev->fontface, &matrix, 0); + FT_Set_Transform(dev->fontface, &matrix, 0); } } @@ -1611,9 +1573,9 @@ handle_char(escp_t *dev, uint8_t ch) /* ok, so we need to print the character now */ if (ft_lib) { - char_index = ft_Get_Char_Index(dev->fontface, dev->curr_cpmap[ch]); - ft_Load_Glyph(dev->fontface, char_index, FT_LOAD_DEFAULT); - ft_Render_Glyph(dev->fontface->glyph, FT_RENDER_MODE_NORMAL); + char_index = FT_Get_Char_Index(dev->fontface, dev->curr_cpmap[ch]); + FT_Load_Glyph(dev->fontface, char_index, FT_LOAD_DEFAULT); + FT_Render_Glyph(dev->fontface->glyph, FT_RENDER_MODE_NORMAL); } pen_x = PIXX + dev->fontface->glyph->bitmap_left; @@ -1986,23 +1948,12 @@ read_status(void *priv) static void * escp_init(void *lpt) { - const char *fn = PATH_FREETYPE_DLL; - escp_t *dev; - - /* Dynamically load FreeType. */ - if (ft_handle == NULL) { - ft_handle = dynld_module(fn, ft_imports); - if (ft_handle == NULL) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2111, (wchar_t *) IDS_2132); - return (NULL); - } - } + escp_t *dev; /* Initialize FreeType. */ if (ft_lib == NULL) { - if (ft_Init_FreeType(&ft_lib)) { + if (FT_Init_FreeType(&ft_lib)) { ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2111, (wchar_t *) IDS_2132); - dynld_close(ft_lib); ft_lib = NULL; return (NULL); } diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 9786b9063..caa166a10 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -51,7 +51,9 @@ #elif defined __APPLE__ # define PATH_GHOSTSCRIPT_DLL "libgs.dylib" #else -# define PATH_GHOSTSCRIPT_DLL "libgs.so.9" +# define PATH_GHOSTSCRIPT_DLL "libgs.so.9" +# define PATH_GHOSTSCRIPT_DLL_ALT1 "libgs.so.10" +# define PATH_GHOSTSCRIPT_DLL_ALT2 "libgs.so" #endif #define POSTSCRIPT_BUFFER_LENGTH 65536 @@ -341,12 +343,21 @@ ps_init(void *lpt) /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); - if (ghostscript_handle == NULL) +#ifdef PATH_GHOSTSCRIPT_DLL_ALT1 + if (ghostscript_handle == NULL) { + ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT1, ghostscript_imports); +# ifdef PATH_GHOSTSCRIPT_DLL_ALT2 + if (ghostscript_handle == NULL) + ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT2, ghostscript_imports); +# endif + } +#endif + if (ghostscript_handle == NULL) { ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2115, (wchar_t *) IDS_2133); - else { - if (gsapi_revision(&rev, sizeof(rev)) == 0) + } else { + if (gsapi_revision(&rev, sizeof(rev)) == 0) { pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); - else { + } else { dynld_close(ghostscript_handle); ghostscript_handle = NULL; } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 30276922f..04317800d 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1299,7 +1299,7 @@ MainWindow::keyReleaseEvent(QKeyEvent *event) fs_on_signal = false; } - if (!send_keyboard_input) + if (!send_keyboard_input || event->isAutoRepeat()) return; #ifdef Q_OS_MACOS diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index e64dc74dd..5f2f81c58 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -36,7 +36,7 @@ SettingsDisplay::SettingsDisplay(QWidget *parent) { ui->setupUi(this); - videoCard[0] = gfxcard[0]; + videoCard[0] = gfxcard[0]; videoCard[1] = gfxcard[1]; onCurrentMachineChanged(machine); } @@ -102,6 +102,11 @@ SettingsDisplay::onCurrentMachineChanged(int machineId) ui->comboBoxVideoSecondary->setEnabled(true); ui->pushButtonConfigureSecondary->setEnabled(true); } + if (video_card_get_flags(gfxcard[0]) != VIDEO_FLAG_TYPE_8514) + ibm8514_has_vga = 0; + if (video_card_get_flags(gfxcard[0]) != VIDEO_FLAG_TYPE_XGA) + xga_has_vga = 0; + ui->comboBoxVideo->setCurrentIndex(selectedRow); if (gfxcard[1] == 0) ui->pushButtonConfigureSecondary->setEnabled(false); @@ -123,10 +128,12 @@ SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() void SettingsDisplay::on_pushButtonConfigureXga_clicked() { - if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { - DeviceConfig::ConfigureDevice(&xga_device, 0, qobject_cast(Settings::settings)); - } else { - DeviceConfig::ConfigureDevice(&xga_isa_device, 0, qobject_cast(Settings::settings)); + if (!xga_has_vga) { + if (machine_has_bus(machineId, MACHINE_BUS_MCA) > 0) { + DeviceConfig::ConfigureDevice(&xga_device, 0, qobject_cast(Settings::settings)); + } else { + DeviceConfig::ConfigureDevice(&xga_isa_device, 0, qobject_cast(Settings::settings)); + } } } @@ -139,7 +146,6 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) auto curVideoCard_2 = videoCard[1]; videoCard[0] = ui->comboBoxVideo->currentData().toInt(); ui->pushButtonConfigure->setEnabled(video_card_has_config(videoCard[0]) > 0); - bool machineHasPci = machine_has_bus(machineId, MACHINE_BUS_PCI) > 0; ui->checkBoxVoodoo->setEnabled(machineHasPci); if (machineHasPci) { @@ -149,16 +155,16 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) bool hasIsa16 = machine_has_bus(machineId, MACHINE_BUS_ISA16) > 0; bool has_MCA = machine_has_bus(machineId, MACHINE_BUS_MCA) > 0; - ui->checkBox8514->setEnabled(hasIsa16 || has_MCA); + ui->checkBox8514->setEnabled((hasIsa16 || has_MCA) && !ibm8514_has_vga); if (hasIsa16 || has_MCA) { ui->checkBox8514->setChecked(ibm8514_enabled); } - ui->checkBoxXga->setEnabled(hasIsa16 || has_MCA); + ui->checkBoxXga->setEnabled((hasIsa16 || has_MCA) && !xga_has_vga); if (hasIsa16 || has_MCA) ui->checkBoxXga->setChecked(xga_enabled); - ui->pushButtonConfigureXga->setEnabled((hasIsa16 || has_MCA) && ui->checkBoxXga->isChecked()); + ui->pushButtonConfigureXga->setEnabled((hasIsa16 || has_MCA) && ui->checkBoxXga->isChecked() && !xga_has_vga); int c = 2; @@ -187,7 +193,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) c++; } - if (videoCard[1] == 0 || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0)) { + if ((videoCard[1] == 0) || (machine_has_flags(machineId, MACHINE_VIDEO_ONLY) > 0)) { ui->comboBoxVideoSecondary->setCurrentIndex(0); ui->pushButtonConfigureSecondary->setEnabled(false); } @@ -202,7 +208,7 @@ SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) void SettingsDisplay::on_checkBoxXga_stateChanged(int state) { - ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked); + ui->pushButtonConfigureXga->setEnabled((state == Qt::Checked) && !xga_has_vga); } void diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index efc2a62ae..5616042ec 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1513,14 +1513,14 @@ buslogic_init(const device_t *info) { x54x_t *dev; char *bios_rom_name; - uint16_t bios_rom_size; - uint16_t bios_rom_mask; + uint16_t bios_rom_size = 0; + uint16_t bios_rom_mask = 0; uint8_t has_autoscsi_rom; - char *autoscsi_rom_name; - uint16_t autoscsi_rom_size; + char *autoscsi_rom_name = NULL; + uint16_t autoscsi_rom_size = 0; uint8_t has_scam_rom; - char *scam_rom_name; - uint16_t scam_rom_size; + char *scam_rom_name = NULL; + uint16_t scam_rom_size = 0; FILE *f; buslogic_data_t *bl; uint32_t bios_rom_addr; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index b20a4b4ab..d100902d2 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -976,7 +976,9 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) break; case 0xc6: case 0xc7: - if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_DRIVEXM_3433"))) { + if (!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_DRIVEXM_3433") || + !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-3301TA_0272") || + !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-5701TA_3136")) { bytes_per_second = 176.0 * 1024.0; bytes_per_second *= (double) dev->drv->cur_speed; } @@ -1000,7 +1002,15 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) break; case 0xc3: if (!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "SONY_CD-ROM_CDU-541_1.0i") || - !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "SONY_CD-ROM_CDU-76S_1.00")) { + !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "SONY_CD-ROM_CDU-76S_1.00") || + !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "PIONEER_CD-ROM_DRM-604X_2403")) { + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + } + break; + case 0xde: + if (!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE74_1.00") || + !strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE464_1.05")) { bytes_per_second = 176.0 * 1024.0; bytes_per_second *= (double) dev->drv->cur_speed; } diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index f3dc6ebaf..c0244ed4f 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -379,9 +379,9 @@ esp_get_cmd(esp_t *dev, uint32_t maxlen) dma_set_drq(dev->DmaChannel, 0); } else { esp_pci_dma_memory_rw(dev, buf, dmalen, WRITE_TO_DEVICE); - dmalen = MIN(fifo8_num_free(&dev->cmdfifo), dmalen); - fifo8_push_all(&dev->cmdfifo, buf, dmalen); } + dmalen = MIN(fifo8_num_free(&dev->cmdfifo), dmalen); + fifo8_push_all(&dev->cmdfifo, buf, dmalen); } else { dmalen = MIN(fifo8_num_used(&dev->fifo), maxlen); esp_log("ESP Get command, dmalen = %i\n", dmalen); @@ -545,6 +545,8 @@ esp_hard_reset(esp_t *dev) dev->do_cmd = 0; dev->rregs[ESP_CFG1] = dev->mca ? dev->HostID : 7; esp_log("ESP Reset\n"); + for (uint8_t i = 0; i < 16; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); timer_stop(&dev->timer); } @@ -569,7 +571,6 @@ esp_do_nodma(esp_t *dev, scsi_device_t *sd) esp_do_cmd(dev); } else { dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); - ; esp_log("CDB offset = %i used\n", dev->cmdfifo_cdb_offset); dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; @@ -665,7 +666,7 @@ esp_do_dma(esp_t *dev, scsi_device_t *sd) count = tdbc = esp_get_tc(dev); - if (dev->mca) { /*See the comment in the esp_do_busid_cmd() function.*/ + if (dev->mca) { if (sd->buffer_length < 0) { if (dev->dma_enabled) goto done; @@ -713,7 +714,7 @@ esp_do_dma(esp_t *dev, scsi_device_t *sd) return; } - esp_log("ESP SCSI dmaleft = %d, async_len = %i, buffer length = %d\n", esp_get_tc(dev), sd->buffer_length); + esp_log("ESP SCSI dmaleft = %d, buffer length = %d\n", esp_get_tc(dev), sd->buffer_length); /* Make sure count is never bigger than buffer_length. */ if (count > dev->xfer_counter) @@ -1082,6 +1083,9 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) esp_pci_soft_reset(dev); break; case CMD_BUSRESET: + for (uint8_t i = 0; i < 16; i++) + scsi_device_reset(&scsi_devices[dev->bus][i]); + if (!(dev->wregs[ESP_CFG1] & CFG1_RESREPT)) { dev->rregs[ESP_RINTR] |= INTR_RST; esp_log("ESP Bus Reset with IRQ\n"); diff --git a/src/sio/sio_82091aa.c b/src/sio/sio_82091aa.c index 800bf1b1a..346d2d435 100644 --- a/src/sio/sio_82091aa.c +++ b/src/sio/sio_82091aa.c @@ -142,7 +142,7 @@ i82091aa_write(uint16_t port, uint8_t val, void *priv) { i82091aa_t *dev = (i82091aa_t *) priv; uint8_t index; - uint8_t valxor; + uint8_t valxor = 0; uint8_t uart = (dev->cur_reg >> 4) - 0x03; uint8_t *reg = &(dev->regs[dev->cur_reg]); diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index 284836704..0feb3ab74 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -65,8 +65,8 @@ ad1848_updatevolmask(ad1848_t *ad1848) static void ad1848_updatefreq(ad1848_t *ad1848) { - double freq; - uint8_t set = 0; + double freq = 0.0; + uint8_t set = 0; if (ad1848->type >= AD1848_TYPE_CS4235) { if (ad1848->xregs[11] & 0x20) { diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index c1b2c3867..e4330cba3 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -20,7 +20,7 @@ typedef struct adgold_t { int adgold_irq_status; - int irq, dma, hdma; + int irq, dma; uint8_t adgold_eeprom[0x1a]; @@ -547,6 +547,7 @@ adgold_read(uint16_t addr, void *p) temp = adgold->adgold_mma_status; adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/ adgold_update_irq_status(adgold); + picintc(1 << adgold->irq); break; case 5: if (adgold->adgold_mma_addr >= 0xf) @@ -652,7 +653,8 @@ adgold_timer_poll(void *p) { adgold_t *adgold = (adgold_t *) p; - timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t) ((double) TIMER_USEC * 1.88964)); + /*A small timer period will result in hangs.*/ + timer_on_auto(&adgold->adgold_mma_timer_count, 4.88964); if (adgold->adgold_midi_ctrl & 0x3f) { if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) { @@ -925,7 +927,7 @@ adgold_init(const device_t *info) adgold->adgold_eeprom[0x10] = 0xff; adgold->adgold_eeprom[0x11] = 0x20; adgold->adgold_eeprom[0x12] = 0x00; - adgold->adgold_eeprom[0x13] = 0xa0; + adgold->adgold_eeprom[0x13] = 0x00; adgold->adgold_eeprom[0x14] = 0x00; adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/ adgold->adgold_eeprom[0x16] = 0x00; @@ -957,6 +959,7 @@ adgold_init(const device_t *info) break; } adgold->adgold_eeprom[0x13] |= (adgold->dma << 3); + adgold->adgold_eeprom[0x14] |= (adgold->dma << 4); memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x19); adgold->vol_l = attenuation[adgold->adgold_eeprom[0x04] & 0x3f]; adgold->vol_r = attenuation[adgold->adgold_eeprom[0x05] & 0x3f]; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 6b9d8d792..53de22ce7 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -311,7 +311,13 @@ es1371_reset(void *p) /* Interrupt/Chip Select Control Register, Address 00H Addressable as longword only */ - dev->int_status = 0x7ffffec0; + /* Bit 13 is supposed to be always 1 on ES1371, and one of the GPIO interrupt + flags on ES1373. The 5.12.01 WDM driver only initializes its GPIO interrupt + handler on chip revisions which support this feature (1371 >= 0x04 and 5880 + all), but calls it anyway during interrupt servicing regardless of revision, + crashing on ES1371 as soon as an interrupt arrives while that bit is set. + Pending hardware research because actual early ES1371 cards are rare. */ + dev->int_status = 0x7fffdec0; /* UART Status Register, Address 09H Addressable as byte only */ @@ -621,11 +627,11 @@ es1371_inb(uint16_t port, void *p) audiopci_log("[R] STATUS 8-15 = %02X\n", ret); break; case 0x06: - ret = (dev->int_status >> 16) & 0x0f; + ret = (dev->int_status >> 16) & 0xff; audiopci_log("[R] STATUS 16-23 = %02X\n", ret); break; case 0x07: - ret = ((dev->int_status >> 24) & 0x03) | 0xfc; + ret = (dev->int_status >> 24) & 0xff; audiopci_log("[R] STATUS 24-31 = %02X\n", ret); break; @@ -1551,7 +1557,7 @@ es1371_pci_read(int func, int addr, void *p) return 0x00; case 0x08: - return 0x08; /* Revision ID - 0x02 (datasheet, VMware) has issues with the 2001 Creative WDM driver */ + return 0x02; /* Revision ID - 0x02 is supposed to be early Ensoniq-branded ES1371 but unconfirmed */ case 0x09: return 0x00; /* Multimedia audio device */ case 0x0a: @@ -2069,10 +2075,6 @@ static const device_config_t es1371_config[] = { .description = "Crystal CS4297A", .value = AC97_CODEC_CS4297A }, - { - .description = "SigmaTel STAC9708", - .value = AC97_CODEC_STAC9708 - }, { .description = "SigmaTel STAC9721", .value = AC97_CODEC_STAC9721 diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 84f31f500..9c25be7a1 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -348,7 +348,7 @@ sb_get_buffer_sb16_awe32(int32_t *buffer, int len, void *p) sb_t *sb = (sb_t *) p; sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; int dsp_rec_pos = sb->dsp.record_pos_write; - int c_emu8k; + int c_emu8k = 0; int c_record; int32_t in_l; int32_t in_r; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index a3a748374..274a0579e 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -79,15 +79,20 @@ static void wss_get_buffer(int32_t *buffer, int len, void *priv) { wss_t *wss = (wss_t *) priv; + int32_t *opl_buf = NULL; + + if (wss->opl_enabled) + opl_buf = wss->opl.update(wss->opl.priv); - int32_t *opl_buf = wss->opl.update(wss->opl.priv); ad1848_update(&wss->ad1848); for (int c = 0; c < len * 2; c++) { - buffer[c] += opl_buf[c]; + if (opl_buf) + buffer[c] += opl_buf[c]; buffer[c] += wss->ad1848.buffer[c] / 2; } - wss->opl.reset_buffer(wss->opl.priv); + if (wss->opl_enabled) + wss->opl.reset_buffer(wss->opl.priv); wss->ad1848.pos = 0; } diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index b37e81134..3d3d2d466 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_incolor.c vid_colorplus.c vid_genius.c vid_pgc.c vid_im1024.c vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c vid_8514a.c vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c - vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c + vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c vid_et3000.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 diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 9ec196d86..ebf2d0b3f 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -7,13 +7,13 @@ * This file is part of the 86Box distribution. * * Emulation of the 8514/A card from IBM for the MCA bus and - * generic ISA bus clones without vendor extensions. + * ISA bus clones. * * * * Authors: TheCollector1995. * - * Copyright 2022 TheCollector1995. + * Copyright 2022-2023 TheCollector1995. */ #include #include @@ -21,6 +21,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> @@ -42,17 +43,53 @@ static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *p); static uint8_t ibm8514_accel_inb(uint16_t port, void *p); static uint16_t ibm8514_accel_inw(uint16_t port, void *p); +#ifdef ENABLE_IBM8514_LOG +int ibm8514_do_log = ENABLE_IBM8514_LOG; + +static void +ibm8514_log(const char *fmt, ...) +{ + va_list ap; + + if (ibm8514_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ibm8514_log(fmt, ...) +#endif + #define READ_PIXTRANS_WORD(cx, n) \ if ((cmd <= 1) || (cmd == 5)) { \ - temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + if (dev->local) { \ + temp = svga->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & svga->vram_mask]; \ + temp |= (svga->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & svga->vram_mask] << 8); \ + } else { \ + temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ } else { \ - temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + if (dev->local) { \ + temp = svga->vram[(dev->accel.dest + (cx) + (n)) & svga->vram_mask]; \ + temp |= (svga->vram[(dev->accel.dest + (cx) + (n + 1)) & svga->vram_mask] << 8); \ + } else { \ + temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ } #define READ(addr, dat) \ - dat = dev->vram[(addr) & (dev->vram_mask)]; + if (dev->local) { \ + if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + dat = vram_w[(addr) & (svga->vram_mask >> 1)]; \ + } else { \ + dat = (svga->vram[(addr) & (svga->vram_mask)]); \ + } \ + } else { \ + dat = (dev->vram[(addr) & (dev->vram_mask)]); \ + } #define MIX(mixmode, dest_dat, src_dat) \ { \ @@ -157,8 +194,20 @@ static uint16_t ibm8514_accel_inw(uint16_t port, void *p); } #define WRITE(addr, dat) \ - dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; + if (dev->local) { \ + if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + vram_w[((addr)) & (svga->vram_mask >> 1)] = dat; \ + svga->changedvram[(((addr)) & (svga->vram_mask >> 1)) >> 11] = changeframecount; \ + } else { \ + svga->vram[((addr)) & (svga->vram_mask)] = dat; \ + svga->changedvram[(((addr)) & (svga->vram_mask)) >> 12] = changeframecount; \ + } \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + } + +int ibm8514_has_vga = 0; int ibm8514_cpu_src(svga_t *svga) @@ -557,10 +606,11 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.short_stroke = val; dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - if (dev->accel.cur_y & 0x400) - dev->accel.cy |= ~0x3ff; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); @@ -573,15 +623,16 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x9ee9: case 0xdee9: + dev->accel.ssv_state = 1; if (len == 1) { dev->accel.short_stroke = (dev->accel.short_stroke & 0xff) | (val << 8); dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - if (dev->accel.cur_y & 0x400) - dev->accel.cy |= ~0x3ff; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -701,10 +752,14 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; if ((dev->accel.multifunc_cntl >> 12) == 1) { - dev->accel.clip_top = val & 0x3ff; + dev->accel.clip_top = val & 0x7ff; + if (val & 0x400) + dev->accel.clip_top |= ~0x3ff; } if ((dev->accel.multifunc_cntl >> 12) == 2) { - dev->accel.clip_left = val & 0x3ff; + dev->accel.clip_left = val & 0x7ff; + if (val & 0x400) + dev->accel.clip_left |= ~0x3ff; } if (port == 0xfee8) dev->accel.cmd_back = 1; @@ -820,24 +875,24 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x2e9: if (len != 1) { dev->htotal = (dev->htotal & 0xff) | (val << 8); - // pclog("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); + ibm8514_log("IBM 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); svga_recalctimings(svga); } break; case 0x6e8: dev->hdisp = val; - // pclog("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); svga_recalctimings(svga); break; case 0xae8: - // pclog("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); svga_recalctimings(svga); break; case 0xee8: - // pclog("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); + ibm8514_log("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); svga_recalctimings(svga); break; @@ -852,7 +907,7 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x12e9: if (len == 1) { dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8); - // pclog("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); + ibm8514_log("IBM 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); svga_recalctimings(svga); } break; @@ -868,7 +923,7 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x16e9: if (len == 1) { dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8); - // pclog("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); svga_recalctimings(svga); } break; @@ -884,21 +939,21 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x1ae9: if (len == 1) { dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8); - // pclog("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); + ibm8514_log("IBM 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); svga_recalctimings(svga); } break; case 0x1ee8: dev->vsyncwidth = val; - // pclog("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); + ibm8514_log("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); svga_recalctimings(svga); break; case 0x22e8: dev->disp_cntl = val & 0x7e; dev->interlace = !!(val & 0x10); - // pclog("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); svga_recalctimings(svga); break; @@ -922,7 +977,7 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) dev->accel.advfunc_cntl = val & 7; ibm8514_on = (dev->accel.advfunc_cntl & 1); vga_on = !ibm8514_on; - //pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + ibm8514_log("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); svga_recalctimings(svga); break; } @@ -1105,26 +1160,33 @@ void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len) { ibm8514_t *dev = &svga->dev8514; - uint8_t src_dat = 0; - uint8_t dest_dat; - uint8_t old_dest_dat; - int frgd_mix; - int bkgd_mix; - uint16_t clip_b = dev->accel.multifunc[3] & 0x7ff; - uint16_t clip_r = dev->accel.multifunc[4] & 0x7ff; + uint16_t *vram_w = (uint16_t *)svga->vram; + uint16_t src_dat = 0, dest_dat, old_dest_dat; + int frgd_mix, bkgd_mix; + uint16_t clip_b = dev->accel.multifunc[3]; + uint16_t clip_r = dev->accel.multifunc[4]; int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; - uint8_t mix_mask = 0x80; - uint8_t compare = dev->accel.color_cmp & 0xff; + uint16_t mix_mask = ((svga->bpp == 8) || (svga->bpp == 24)) ? 0x80 : 0x8000; + uint16_t compare = dev->accel.color_cmp; int compare_mode = dev->accel.multifunc[0x0a] & 0x38; int cmd = dev->accel.cmd >> 13; - uint8_t wrt_mask = dev->accel.wrt_mask & 0xff; - uint8_t rd_mask = ((dev->accel.rd_mask & 0x01) << 7) | ((dev->accel.rd_mask & 0xfe) >> 1); - uint8_t rd_mask_polygon = dev->accel.rd_mask & 0xff; - uint8_t frgd_color = dev->accel.frgd_color; - uint8_t bkgd_color = dev->accel.bkgd_color; + uint16_t wrt_mask = dev->accel.wrt_mask; + uint16_t rd_mask = dev->accel.rd_mask; + uint16_t rd_mask_polygon = dev->accel.rd_mask; + uint16_t frgd_color = dev->accel.frgd_color; + uint16_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; int and3 = dev->accel.cur_x & 3; - uint8_t poly_src = 0; + uint16_t poly_src = 0; + + if ((svga->bpp == 8) || (svga->bpp == 24)) { + compare &= 0xff; + frgd_color &= 0xff; + bkgd_color &= 0xff; + rd_mask = ((dev->accel.rd_mask & 0x01) << 7) | ((dev->accel.rd_mask & 0xfe) >> 1); + rd_mask &= 0xff; + rd_mask_polygon &= 0xff; + } if (dev->accel.cmd & 0x100) { dev->force_busy = 1; @@ -1147,6 +1209,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } else { count >>= 3; } + + if (((svga->bpp == 15) || (svga->bpp == 16))) { + if ((dev->accel.cmd & 0x200) && (count == 2)) + count >>= 1; + } } if (pixcntl == 1) { @@ -1246,7 +1313,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -1255,17 +1322,26 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); if (dev->accel.ssv_draw) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 4) && dev->accel.ssv_len) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } } } } mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (!dev->accel.ssv_len) break; @@ -1303,10 +1379,116 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.ssv_len--; } + } else { + while (count-- && (dev->accel.ssv_len >= 0)) { + if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + + if (dev->accel.ssv_draw) { + if ((dev->accel.cmd & 4) && dev->accel.ssv_len) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 4)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } + } + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + if (!dev->accel.ssv_len) + break; + + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cy--; + break; + case 0x20: + dev->accel.cy--; + break; + case 0x40: + dev->accel.cx--; + break; + case 0x60: + dev->accel.cx++; + break; + case 0x80: + dev->accel.cy++; + break; + case 0xa0: + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cx--; + break; + case 0xe0: + dev->accel.cx++; + break; + } + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx--; + break; + case 0x20: + dev->accel.cx++; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cy++; + break; + } + + dev->accel.ssv_len--; + } } + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; break; case 1: /*Draw line*/ @@ -1315,11 +1497,11 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) { - dev->accel.cx |= ~0x3ff; + if (dev->accel.cur_x >= 0x600) { + dev->accel.cx |= ~0x5ff; } - if (dev->accel.cur_y & 0x400) { - dev->accel.cy |= ~0x3ff; + if (dev->accel.cur_y >= 0x600) { + dev->accel.cy |= ~0x5ff; } dev->accel.sy = dev->accel.maj_axis_pcnt; @@ -1392,7 +1574,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -1477,7 +1659,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.sy == 0) { break; @@ -1538,7 +1723,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -1561,7 +1746,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.temp_cnt--; mix_dat >>= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.sy == 0) { break; @@ -1654,7 +1842,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -1677,7 +1865,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.sy == 0) { break; @@ -1767,14 +1958,18 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - dev->accel.cx = dev->accel.cur_x & 0x3ff; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - dev->accel.cy = dev->accel.cur_y & 0x3ff; - if (dev->accel.cur_y & 0x400) - dev->accel.cy |= ~0x3ff; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + dev->accel.cy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; - dev->accel.dest = dev->accel.cy * dev->pitch; + if (dev->local && dev->accel.ge_offset && (svga->bpp == 24)) + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + else + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.fill_state = 0; if (cmd == 4) @@ -1822,7 +2017,10 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.output = 1; - dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; + if (dev->local && dev->accel.ge_offset && (svga->bpp == 24)) + dev->accel.newdest_out = (dev->accel.ge_offset << 2) + ((dev->accel.cy + 1) * dev->pitch); + else + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; } } } @@ -1864,7 +2062,7 @@ rect_fill_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -1939,7 +2137,10 @@ rect_fill_pix: mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; switch (dev->accel.cmd & 0xe0) { case 0x00: @@ -2033,7 +2234,7 @@ rect_fill_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -2052,7 +2253,10 @@ rect_fill_pix: mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2077,7 +2281,11 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->pitch; + if (dev->local && dev->accel.ge_offset && (svga->bpp == 24)) + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + else + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.sy--; return; } @@ -2107,7 +2315,7 @@ rect_fill_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -2125,7 +2333,10 @@ rect_fill_pix: } } mix_dat >>= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2148,9 +2359,9 @@ rect_fill_pix: if (dev->accel.cmd & 2) { if (dev->accel.cmd & 0x1000) { - dev->accel.cx = dev->accel.cur_x & 0x3ff; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; } } @@ -2159,7 +2370,11 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->pitch; + if (dev->local && dev->accel.ge_offset && (svga->bpp == 24)) + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); + else + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.sy--; return; } @@ -2262,7 +2477,10 @@ rect_fill_pix: } mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2333,7 +2551,7 @@ rect_fill_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -2358,7 +2576,10 @@ rect_fill_pix: mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) dev->accel.cx++; @@ -2671,8 +2892,12 @@ rect_fill: if (!cpu_input) { dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - dev->accel.oldcy = dev->accel.cy; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; + dev->accel.oldcy = dev->accel.cy; dev->accel.sy = 0; if (ibm8514_cpu_src(svga)) { @@ -2687,9 +2912,6 @@ rect_fill: } while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cur_x > 1023) - dev->accel.cx = 0; - if ((dev->accel.cx) >= dev->accel.clip_left && ((dev->accel.cx) <= clip_r) && (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: @@ -2699,7 +2921,7 @@ rect_fill: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: src_dat = 0; @@ -2726,7 +2948,10 @@ rect_fill: mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.sy == dev->accel.maj_axis_pcnt) { break; @@ -2813,21 +3038,21 @@ rect_fill: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; dev->accel.sy = dev->accel.multifunc[0] & 0x7ff; - dev->accel.dx = dev->accel.destx_distp & 0x3ff; - dev->accel.dy = dev->accel.desty_axstp & 0x3ff; + dev->accel.dx = dev->accel.destx_distp; + dev->accel.dy = dev->accel.desty_axstp; - if (dev->accel.destx_distp & 0x400) - dev->accel.dx |= ~0x3ff; - if (dev->accel.desty_axstp & 0x400) - dev->accel.dy |= ~0x3ff; + if (dev->accel.destx_distp >= 0x600) + dev->accel.dx |= ~0x5ff; + if (dev->accel.desty_axstp >= 0x600) + dev->accel.dy |= ~0x5ff; - dev->accel.cx = dev->accel.cur_x & 0x3ff; - dev->accel.cy = dev->accel.cur_y & 0x3ff; + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - if (dev->accel.cur_y & 0x400) - dev->accel.cy |= ~0x3ff; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + if (dev->accel.cur_y >= 0x600) + dev->accel.cy |= ~0x5ff; dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.dest = dev->accel.dy * dev->pitch; @@ -2876,7 +3101,7 @@ bitblt_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: READ(dev->accel.src + dev->accel.cx, src_dat); @@ -2900,12 +3125,18 @@ bitblt_pix: mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; - - if (dev->accel.cmd & 0x20) - dev->accel.cx++; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; else + cpu_dat >>= 8; + + if (dev->accel.cmd & 0x20) { + dev->accel.dx++; + dev->accel.cx++; + } else { + dev->accel.dx--; dev->accel.cx--; + } dev->accel.sx--; if (dev->accel.sx < 0) { @@ -2916,16 +3147,23 @@ bitblt_pix: } if (dev->accel.cmd & 0x20) { + dev->accel.dx -= (dev->accel.sx) + 1; dev->accel.cx -= (dev->accel.sx) + 1; - } else + } else { + dev->accel.dx += (dev->accel.sx) + 1; dev->accel.cx += (dev->accel.sx) + 1; + } - if (dev->accel.cmd & 0x80) + if (dev->accel.cmd & 0x80) { + dev->accel.dy++; dev->accel.cy++; - else + } else { + dev->accel.dy--; dev->accel.cy--; + } - dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.dest = dev->accel.dy * dev->pitch; dev->accel.sy--; return; } @@ -2952,7 +3190,7 @@ bitblt_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: READ(dev->accel.src + dev->accel.cx, src_dat); @@ -2974,7 +3212,10 @@ bitblt_pix: } } mix_dat >>= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) { dev->accel.dx++; @@ -3003,12 +3244,12 @@ bitblt_pix: if (dev->accel.cmd & 2) { if (dev->accel.cmd & 0x1000) { - dev->accel.cx = dev->accel.cur_x & 0x3ff; - if (dev->accel.cur_x & 0x400) - dev->accel.cx |= ~0x3ff; - dev->accel.dx = dev->accel.destx_distp & 0x3ff; - if (dev->accel.destx_distp & 0x400) - dev->accel.dx |= ~0x3ff; + dev->accel.cx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.cx |= ~0x5ff; + dev->accel.dx = dev->accel.destx_distp; + if (dev->accel.destx_distp >= 0x600) + dev->accel.dx |= ~0x5ff; } } @@ -3056,7 +3297,7 @@ bitblt_pix: src_dat = frgd_color; break; case 2: - src_dat = cpu_dat & 0xff; + src_dat = cpu_dat; break; case 3: READ(dev->accel.src + dev->accel.cx, src_dat); @@ -3079,7 +3320,10 @@ bitblt_pix: } mix_dat <<= 1; mix_dat |= 1; - cpu_dat >>= 8; + if ((svga->bpp == 15) || (svga->bpp == 16)) + cpu_dat >>= 16; + else + cpu_dat >>= 8; if (dev->accel.cmd & 0x20) { dev->accel.dx++; @@ -3123,7 +3367,7 @@ bitblt: count = dev->accel.maj_axis_pcnt + 1; dev->accel.temp_cnt = 8; while (count-- && dev->accel.sy >= 0) { - if (dev->accel.temp_cnt == 0) { + if (!dev->accel.temp_cnt) { mix_dat >>= 8; dev->accel.temp_cnt = 8; } @@ -3197,7 +3441,7 @@ bitblt: } else { dev->accel.temp_cnt = 8; while (count-- && dev->accel.sy >= 0) { - if (dev->accel.temp_cnt == 0) { + if (!dev->accel.temp_cnt) { dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } @@ -3269,6 +3513,32 @@ bitblt: } } } else { + if ((svga->bpp == 24) && dev->local && (dev->accel.cmd == 0xc2b5)) { + int64_t cx, dx; + + cx = (int64_t)dev->accel.cx; + dx = (int64_t)dev->accel.dx; + + while (1) { + if (((dx) >= (((int64_t)dev->accel.clip_left) * 3) && (dx) <= (((uint64_t)clip_r) * 3) && dev->accel.dy >= (dev->accel.clip_top << 1) && dev->accel.dy <= (clip_b << 1))) { + READ(dev->accel.src + (dev->accel.ge_offset << 2) + cx, src_dat); + READ(dev->accel.dest + (dev->accel.ge_offset << 2) + dx, dest_dat); + + dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); + + WRITE(dev->accel.dest + (dev->accel.ge_offset << 2) + dx, dest_dat); + } + + cx++; + dx++; + + dev->accel.sx--; + if (dev->accel.sx < 0) + return; + } + return; + } + while (count-- && dev->accel.sy >= 0) { if (dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b) { if (pixcntl == 3) { @@ -3309,7 +3579,13 @@ bitblt: MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + if (dev->accel.cmd & 4) { + if (dev->accel.sx > 0) { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } } } mix_dat <<= 1; @@ -3547,7 +3823,7 @@ ibm8514_recalctimings(svga_t *svga) if (ibm8514_on) { dev->h_disp = (dev->hdisp + 1) << 3; - dev->pitch = dev->h_disp; + dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640; dev->h_total = (dev->htotal + 1); dev->v_total = (dev->vtotal + 1); dev->v_syncstart = (dev->vsyncstart + 1); @@ -3555,46 +3831,9 @@ ibm8514_recalctimings(svga_t *svga) dev->dispend = ((dev->vdisp >> 1) + 1); if (dev->dispend == 766) dev->dispend = 768; - //pclog("HDISP = %d, VTOTAL = %d, DISPEND = %d, hires = %02x\n", dev->h_disp, dev->v_total, dev->dispend, dev->accel.advfunc_cntl & 4); - { -#if 0 - if (dev->dispend == 480) { - dev->h_disp = 640; - dev->rowoffset = 128; - dev->pitch = 1024; - } else if ((dev->dispend == 600) || (dev->dispend == 598)) { - dev->h_disp = 800; - dev->rowoffset = 128; - dev->dispend = 600; - dev->pitch = 1024; - if (!dev->vtotal) - dev->v_total = 816; - if (!dev->vsyncstart) - dev->v_syncstart = dev->dispend; - } else { - if (dev->accel.advfunc_cntl & 4) { - if (!dev->hdisp) { - dev->rowoffset = 128; - dev->h_disp = 1024; - dev->pitch = dev->h_disp; - } - if (!dev->vtotal) - dev->v_total = 816; - if (!dev->vsyncstart) - dev->v_syncstart = dev->dispend; - } else { - dev->rowoffset = 128; - dev->h_disp = 640; - dev->dispend = 480; - dev->pitch = 1024; - if (!dev->vtotal) - dev->v_total = 816; - if (!dev->vsyncstart) - dev->v_syncstart = dev->dispend; - } - } -#endif - } + + if (dev->dispend == 598) + dev->dispend = 600; if (dev->accel.advfunc_cntl & 4) { if (!vga_on && dev->ibm_mode) { @@ -3617,15 +3856,21 @@ ibm8514_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } - dev->rowoffset = 0x80; - dev->pitch = 1024; - // pclog("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); + if (ibm8514_has_vga) { + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + } else + dev->rowoffset = 128; + + ibm8514_log("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; } else { if (!vga_on && dev->ibm_mode) { - dev->h_disp = 640; - dev->dispend = 480; + if (dev->h_disp == 1024) { + dev->h_disp = 640; + dev->dispend = 480; + } } if (dev->interlace) { @@ -3636,15 +3881,19 @@ ibm8514_recalctimings(svga_t *svga) dev->v_syncstart >>= 1; dev->v_total >>= 1; } - dev->rowoffset = 0x80; - dev->pitch = 1024; + + if (ibm8514_has_vga) { + dev->pitch = dev->ext_pitch; + dev->rowoffset = dev->ext_crt_pitch; + } else + dev->rowoffset = 128; svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; } svga->render = ibm8514_render_8bpp; - //pclog("Pitch = %d, mode = %d.\n", dev->pitch, dev->ibm_mode); + ibm8514_log("BPP=%d, Pitch = %d, rowoffset = %d, crtc13 = %02x, mode = %d, highres bit = %02x, has_vga? = %d.\n", dev->bpp, dev->pitch, dev->rowoffset, svga->crtc[0x13], dev->ibm_mode, dev->accel.advfunc_cntl & 4, ibm8514_has_vga); } - // pclog("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); + ibm8514_log("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); } static uint8_t @@ -3697,6 +3946,7 @@ static void dev->type = info->flags; dev->ibm_mode = 1; + dev->bpp = 8; ibm8514_io_set(svga); @@ -3770,7 +4020,7 @@ const device_t ibm8514_mca_device = { void ibm8514_device_add(void) { - if (!ibm8514_enabled) + if (!ibm8514_enabled || (ibm8514_enabled && ibm8514_has_vga)) return; if (machine_has_bus(machine, MACHINE_BUS_MCA)) diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 2e10216e4..10b37212d 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -45,6 +45,26 @@ ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type) fclose(f); } +void +ati_eeprom_load_mach8(ati_eeprom_t *eeprom, char *fn) +{ + FILE *f; + int size; + eeprom->type = 0; + strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1); + f = nvr_fopen(eeprom->fn, "rb"); + size = 128; + if (!f) { /*The ATI Graphics Ultra bios expects an immediate write to nvram if none is present at boot time otherwise + it would hang the machine.*/ + memset(eeprom->data, 0, size); + f = nvr_fopen(eeprom->fn, "wb"); + fwrite(eeprom->data, 1, size, f); + } + if (fread(eeprom->data, 1, size, f) != size) + memset(eeprom->data, 0, size); + fclose(f); +} + void ati_eeprom_save(ati_eeprom_t *eeprom) { diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 273dbdcf6..39371e882 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -172,7 +172,7 @@ typedef struct mach64_t { uint32_t write_mask; uint32_t chain_mask; - uint32_t linear_base, old_linear_base; + uint32_t linear_base; uint32_t io_base; struct @@ -185,6 +185,7 @@ typedef struct mach64_t { int src_x_start, src_y_start; int xinc, yinc; int x_count, y_count; + int xx_count; int src_x_count, src_y_count; int src_width1, src_height1; int src_width2, src_height2; @@ -487,35 +488,35 @@ mach64_recalctimings(svga_t *svga) case BPP_4: if (mach64->type != MACH64_GX) svga->render = svga_render_4bpp_highres; - svga->hdisp *= 8; + svga->hdisp <<= 3; break; case BPP_8: if (mach64->type != MACH64_GX) svga->render = svga_render_8bpp_highres; - svga->hdisp *= 8; - svga->rowoffset /= 2; + svga->hdisp <<= 3; + svga->rowoffset >>= 1; break; case BPP_15: if (mach64->type != MACH64_GX) svga->render = svga_render_15bpp_highres; - svga->hdisp *= 8; + svga->hdisp <<= 3; break; case BPP_16: if (mach64->type != MACH64_GX) svga->render = svga_render_16bpp_highres; - svga->hdisp *= 8; + svga->hdisp <<= 3; break; case BPP_24: if (mach64->type != MACH64_GX) svga->render = svga_render_24bpp_highres; - svga->hdisp *= 8; + svga->hdisp <<= 3; svga->rowoffset = (svga->rowoffset * 3) / 2; break; case BPP_32: if (mach64->type != MACH64_GX) svga->render = svga_render_32bpp_highres; - svga->hdisp *= 8; - svga->rowoffset *= 2; + svga->hdisp <<= 3; + svga->rowoffset <<= 1; break; } @@ -530,7 +531,7 @@ mach64_updatemapping(mach64_t *mach64) { svga_t *svga = &mach64->svga; - if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + if (mach64->pci && !(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { mach64_log("Update mapping - PCI disabled\n"); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&mach64->linear_mapping); @@ -543,47 +544,60 @@ mach64_updatemapping(mach64_t *mach64) mem_mapping_disable(&mach64->mmio_mapping); switch (svga->gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); - mem_mapping_set_p(&mach64->svga.mapping, mach64); + mem_mapping_set_handler(&svga->mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); + mem_mapping_set_p(&svga->mapping, mach64); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); mem_mapping_enable(&mach64->mmio_mapping); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); - mem_mapping_set_p(&mach64->svga.mapping, mach64); + mem_mapping_set_handler(&svga->mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); + mem_mapping_set_p(&svga->mapping, mach64); mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&mach64->svga.mapping, svga); + mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_mapping_set_p(&svga->mapping, svga); mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&mach64->svga.mapping, svga); + mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_mapping_set_p(&svga->mapping, svga); mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } + + mach64_log("Mach64 linear aperture = %08x.\n", mach64->linear_base); if (mach64->linear_base) { if (mach64->type == MACH64_GX) { if ((mach64->config_cntl & 3) == 2) { /*8 MB aperture*/ mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); - } else { + } else if ((mach64->config_cntl & 3) == 1) { /*4 MB aperture*/ mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (4 << 20) - 0x4000); mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((4 << 20) - 0x4000), 0x4000); + } else { + /*Disable aperture on reserved values*/ + mem_mapping_disable(&mach64->linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping); } } else { - /*2*8 MB aperture*/ - mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); + if ((mach64->config_cntl & 3) == 2) { + /*2*8 MB aperture*/ + mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); + mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); + mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); + } else { + /*Disable aperture on reserved values*/ + mem_mapping_disable(&mach64->linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping); + mem_mapping_disable(&mach64->mmio_linear_mapping_2); + } } } else { mem_mapping_disable(&mach64->linear_mapping); @@ -621,7 +635,7 @@ mach64_wait_fifo_idle(mach64_t *mach64) } #define READ8(addr, var) \ - switch ((addr) &3) { \ + switch ((addr) & 3) { \ case 0: \ ret = (var) &0xff; \ break; \ @@ -637,7 +651,7 @@ mach64_wait_fifo_idle(mach64_t *mach64) } #define WRITE8(addr, var, val) \ - switch ((addr) &3) { \ + switch ((addr) & 3) { \ case 0: \ var = (var & 0xffffff00) | (val); \ break; \ @@ -1181,8 +1195,13 @@ mach64_start_fill(mach64_t *mach64) { mach64->accel.dst_x = 0; mach64->accel.dst_y = 0; + mach64->accel.dst_x_start = (mach64->dst_y_x >> 16) & 0xfff; - mach64->accel.dst_y_start = mach64->dst_y_x & 0xfff; + if (((mach64->dst_y_x >> 16) & 0x1000)) + mach64->accel.dst_x_start |= ~0xfff; + mach64->accel.dst_y_start = mach64->dst_y_x & 0x3fff; + if (mach64->dst_y_x & 0x4000) + mach64->accel.dst_y_start |= ~0x3fff; mach64->accel.dst_width = (mach64->dst_height_width >> 16) & 0x1fff; mach64->accel.dst_height = mach64->dst_height_width & 0x1fff; @@ -1193,11 +1212,18 @@ mach64_start_fill(mach64_t *mach64) } mach64->accel.x_count = mach64->accel.dst_width; + mach64->accel.xx_count = 0; mach64->accel.src_x = 0; mach64->accel.src_y = 0; + mach64->accel.src_x_start = (mach64->src_y_x >> 16) & 0xfff; - mach64->accel.src_y_start = mach64->src_y_x & 0xfff; + if (((mach64->src_y_x >> 16) & 0x1000)) + mach64->accel.src_x_start |= ~0xfff; + mach64->accel.src_y_start = mach64->src_y_x & 0x3fff; + if (mach64->src_y_x & 0x4000) + mach64->accel.src_y_start |= ~0x3fff; + if (mach64->src_cntl & SRC_LINEAR_EN) mach64->accel.src_x_count = 0x7ffffff; /*Essentially infinite*/ else @@ -1219,11 +1245,11 @@ mach64_start_fill(mach64_t *mach64) mach64->src_height1_width1, mach64->src_height2_width2); - mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) * 8; - mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8; + mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) << 3; + mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) << 3; - mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8; - mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8; + mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) << 3; + mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) << 3; mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f; mach64->accel.mix_bg = mach64->dp_mix & 0x1f; @@ -1308,16 +1334,24 @@ void mach64_start_line(mach64_t *mach64) { mach64->accel.dst_x = (mach64->dst_y_x >> 16) & 0xfff; - mach64->accel.dst_y = mach64->dst_y_x & 0xfff; + if (((mach64->dst_y_x >> 16) & 0x1000)) + mach64->accel.dst_x |= ~0xfff; + mach64->accel.dst_y = mach64->dst_y_x & 0x3fff; + if (mach64->dst_y_x & 0x4000) + mach64->accel.dst_y |= ~0x3fff; mach64->accel.src_x = (mach64->src_y_x >> 16) & 0xfff; - mach64->accel.src_y = mach64->src_y_x & 0xfff; + if (((mach64->src_y_x >> 16) & 0x1000)) + mach64->accel.src_x |= ~0xfff; + mach64->accel.src_y = mach64->src_y_x & 0x3fff; + if (mach64->src_y_x & 0x4000) + mach64->accel.src_y |= ~0x3fff; - mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) * 8; - mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) * 8; + mach64->accel.src_pitch = (mach64->src_off_pitch >> 22) << 3; + mach64->accel.src_offset = (mach64->src_off_pitch & 0xfffff) << 3; - mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) * 8; - mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) * 8; + mach64->accel.dst_pitch = (mach64->dst_off_pitch >> 22) << 3; + mach64->accel.dst_offset = (mach64->dst_off_pitch & 0xfffff) << 3; mach64->accel.mix_fg = (mach64->dp_mix >> 16) & 0x1f; mach64->accel.mix_bg = mach64->dp_mix & 0x1f; @@ -1344,9 +1378,6 @@ mach64_start_line(mach64_t *mach64) else mach64->accel.dst_offset >>= mach64->accel.dst_size; - /* mach64->accel.src_pitch *= mach64_inc[mach64->accel.src_pix_width]; - mach64->accel.dst_pitch *= mach64_inc[mach64->accel.dst_pix_width];*/ - mach64->accel.source_host = ((mach64->dp_src & 7) == SRC_HOST) || (((mach64->dp_src >> 8) & 7) == SRC_HOST); for (uint8_t y = 0; y < 8; y++) { @@ -1446,6 +1477,7 @@ mach64_start_line(mach64_t *mach64) break; \ case 0x17: \ dest_dat = (dest_dat + src_dat) >> 1; \ + break; \ } #define WRITE(addr, width) \ @@ -1483,24 +1515,31 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) mach64_log("mach64_blit : return as not busy\n"); return; } + switch (mach64->accel.op) { case OP_RECT: while (count) { + uint8_t write_mask = 0; uint32_t src_dat = 0; uint32_t dest_dat; uint32_t host_dat = 0; uint32_t old_dest_dat; int mix = 0; - int dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff; - int dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0xfff; + int dst_x; + int dst_y; int src_x; - int src_y = (mach64->accel.src_y + mach64->accel.src_y_start) & 0xfff; + int src_y; + + dst_x = (mach64->accel.dst_x + mach64->accel.dst_x_start) & 0xfff; + dst_y = (mach64->accel.dst_y + mach64->accel.dst_y_start) & 0x3fff; if (mach64->src_cntl & SRC_LINEAR_EN) src_x = mach64->accel.src_x; else src_x = (mach64->accel.src_x + mach64->accel.src_x_start) & 0xfff; + src_y = (mach64->accel.src_y + mach64->accel.src_y_start) & 0x3fff; + if (mach64->accel.source_host) { host_dat = cpu_dat; switch (mach64->accel.host_size) { @@ -1525,7 +1564,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) mix = cpu_dat & 1; cpu_dat >>= 1; } else { - mix = cpu_dat >> 31; + mix = cpu_dat >> 0x1f; cpu_dat <<= 1; } break; @@ -1544,7 +1583,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) break; } - if (dst_x >= mach64->accel.sc_left && dst_x <= mach64->accel.sc_right && dst_y >= mach64->accel.sc_top && dst_y <= mach64->accel.sc_bottom) { + if ((dst_x) >= mach64->accel.sc_left && (dst_x) <= mach64->accel.sc_right && (dst_y) >= mach64->accel.sc_top && (dst_y) <= mach64->accel.sc_bottom) { switch (mix ? mach64->accel.source_fg : mach64->accel.source_bg) { case SRC_HOST: src_dat = host_dat; @@ -1553,24 +1592,42 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) READ(mach64->accel.src_offset + (src_y * mach64->accel.src_pitch) + src_x, src_dat, mach64->accel.src_size); break; case SRC_FG: - if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) == (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { - if ((mach64->accel.x_count % 3) == 2) - src_dat = mach64->accel.dp_frgd_clr & 0xff; - else if ((mach64->accel.x_count % 3) == 1) - src_dat = (mach64->accel.dp_frgd_clr >> 8) & 0xff; - else if ((mach64->accel.x_count % 3) == 0) - src_dat = (mach64->accel.dp_frgd_clr >> 16) & 0xff; + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + if (mach64->accel.xinc == -1) { + if ((mach64->accel.xx_count % 3) == 2) + src_dat = mach64->accel.dp_frgd_clr & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + src_dat = (mach64->accel.dp_frgd_clr >> 8) & 0xff; + else + src_dat = (mach64->accel.dp_frgd_clr >> 16) & 0xff; + } else { + if ((mach64->accel.xx_count % 3) == 2) + src_dat = (mach64->accel.dp_frgd_clr >> 16) & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + src_dat = (mach64->accel.dp_frgd_clr >> 8) & 0xff; + else + src_dat = mach64->accel.dp_frgd_clr & 0xff; + } } else src_dat = mach64->accel.dp_frgd_clr; break; case SRC_BG: - if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) == (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { - if ((mach64->accel.x_count % 3) == 2) - src_dat = mach64->accel.dp_bkgd_clr & 0xff; - else if ((mach64->accel.x_count % 3) == 1) - src_dat = (mach64->accel.dp_bkgd_clr >> 8) & 0xff; - else if ((mach64->accel.x_count % 3) == 0) - src_dat = (mach64->accel.dp_bkgd_clr >> 16) & 0xff; + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + if (mach64->accel.xinc == -1) { + if ((mach64->accel.xx_count % 3) == 2) + src_dat = mach64->accel.dp_bkgd_clr & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + src_dat = (mach64->accel.dp_bkgd_clr >> 8) & 0xff; + else + src_dat = (mach64->accel.dp_bkgd_clr >> 16) & 0xff; + } else { + if ((mach64->accel.xx_count % 3) == 2) + src_dat = (mach64->accel.dp_bkgd_clr >> 16) & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + src_dat = (mach64->accel.dp_bkgd_clr >> 8) & 0xff; + else + src_dat = mach64->accel.dp_bkgd_clr & 0xff; + } } else src_dat = mach64->accel.dp_bkgd_clr; break; @@ -1595,7 +1652,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) } if (!(mach64->dst_cntl & DST_POLYGON_EN) || mach64->accel.poly_draw) { - READ(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, dest_dat, mach64->accel.dst_size); + READ(mach64->accel.dst_offset + ((dst_y) * mach64->accel.dst_pitch) + (dst_x), dest_dat, mach64->accel.dst_size); switch (mach64->accel.clr_cmp_fn) { case 1: /*TRUE*/ @@ -1612,19 +1669,30 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (!cmp_clr) { old_dest_dat = dest_dat; MIX - dest_dat - = (dest_dat & mach64->accel.write_mask) | (old_dest_dat & ~mach64->accel.write_mask); + + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + if (mach64->accel.xinc == -1) { + if ((mach64->accel.xx_count % 3) == 2) + write_mask = mach64->accel.write_mask & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + write_mask = (mach64->accel.write_mask >> 8) & 0xff; + else + write_mask = (mach64->accel.write_mask >> 16) & 0xff; + } else { + if ((mach64->accel.xx_count % 3) == 2) + write_mask = (mach64->accel.write_mask >> 16) & 0xff; + else if ((mach64->accel.xx_count % 3) == 1) + write_mask = (mach64->accel.write_mask >> 8) & 0xff; + else + write_mask = mach64->accel.write_mask & 0xff; + } + dest_dat = (dest_dat & write_mask) | (old_dest_dat & ~write_mask); + } else { + dest_dat = (dest_dat & mach64->accel.write_mask) | (old_dest_dat & ~mach64->accel.write_mask); + } } - WRITE(mach64->accel.dst_offset + (dst_y * mach64->accel.dst_pitch) + dst_x, mach64->accel.dst_size); - } - } - - if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { - if ((mach64->dst_cntl & (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) != (DST_LAST_PEL | DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)) { - mach64->accel.dp_frgd_clr = ((mach64->accel.dp_frgd_clr >> 8) & 0xffff) | (mach64->accel.dp_frgd_clr << 16); - mach64->accel.dp_bkgd_clr = ((mach64->accel.dp_bkgd_clr >> 8) & 0xffff) | (mach64->accel.dp_bkgd_clr << 16); - mach64->accel.write_mask = ((mach64->accel.write_mask >> 8) & 0xffff) | (mach64->accel.write_mask << 16); + WRITE(mach64->accel.dst_offset + ((dst_y) * mach64->accel.dst_pitch) + (dst_x), mach64->accel.dst_size); } } @@ -1636,14 +1704,18 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) mach64->accel.src_x = 0; if ((mach64->src_cntl & (SRC_PATT_ROT_EN | SRC_PATT_EN)) == (SRC_PATT_ROT_EN | SRC_PATT_EN)) { mach64->accel.src_x_start = (mach64->src_y_x_start >> 16) & 0xfff; + if ((mach64->src_y_x_start >> 16) & 0x1000) + mach64->accel.src_x_start |= ~0xfff; mach64->accel.src_x_count = mach64->accel.src_width2; } else mach64->accel.src_x_count = mach64->accel.src_width1; } } + mach64->accel.xx_count++; mach64->accel.x_count--; if (mach64->accel.x_count <= 0) { + mach64->accel.xx_count = 0; mach64->accel.x_count = mach64->accel.dst_width; mach64->accel.dst_x = 0; mach64->accel.dst_y += mach64->accel.yinc; @@ -1657,7 +1729,9 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.src_y_count <= 0) { mach64->accel.src_y = 0; if ((mach64->src_cntl & (SRC_PATT_ROT_EN | SRC_PATT_EN)) == (SRC_PATT_ROT_EN | SRC_PATT_EN)) { - mach64->accel.src_y_start = mach64->src_y_x_start & 0xfff; + mach64->accel.src_y_start = mach64->src_y_x_start & 0x3fff; + if (mach64->src_y_x_start & 0x4000) + mach64->accel.src_y_start |= ~0x3fff; mach64->accel.src_y_count = mach64->accel.src_height2; } else mach64->accel.src_y_count = mach64->accel.src_height1; @@ -1702,7 +1776,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.source_host) { host_dat = cpu_dat; - switch (mach64->accel.src_size) { + switch (mach64->accel.host_size) { case 0: cpu_dat >>= 8; count -= 8; @@ -1783,12 +1857,10 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (!cmp_clr) MIX - if (!(mach64->dst_cntl & DST_Y_MAJOR)) - { - if (x == 0) - dest_dat &= ~1; - } - else { + if (!(mach64->dst_cntl & DST_Y_MAJOR)) { + if (!x) + dest_dat &= ~1; + } else { if (x == (mach64->accel.x_count - 1)) dest_dat &= ~1; } @@ -1831,7 +1903,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.source_host) { host_dat = cpu_dat; - switch (mach64->accel.src_size) { + switch (mach64->accel.host_size) { case 0: cpu_dat >>= 8; count -= 8; @@ -1909,7 +1981,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (!cmp_clr) MIX - WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); + WRITE(mach64->accel.dst_offset + (mach64->accel.dst_y * mach64->accel.dst_pitch) + mach64->accel.dst_x, mach64->accel.dst_size); } mach64->accel.x_count--; @@ -2347,6 +2419,7 @@ mach64_ext_readb(uint32_t addr, void *p) mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 22) << 4); else mach64->config_cntl = (mach64->config_cntl & ~0x3ff0) | ((mach64->linear_base >> 24) << 4); + READ8(addr, mach64->config_cntl); break; case 0xe0: @@ -2667,11 +2740,15 @@ mach64_ext_readb(uint32_t addr, void *p) case 0x310: case 0x311: - if (!FIFO_EMPTY) - wake_fifo_thread(mach64); - ret = 0; - if (FIFO_FULL) - ret = 0xff; + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) { + ret = 0; + } else { + if (!FIFO_EMPTY) + wake_fifo_thread(mach64); + ret = 0; + if (FIFO_FULL) + ret = 0xff; + } break; case 0x320: @@ -2697,7 +2774,10 @@ mach64_ext_readb(uint32_t addr, void *p) break; case 0x338: - ret = FIFO_EMPTY ? 0 : 1; + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) + ret = 0; + else + ret = FIFO_EMPTY ? 0 : 1; break; default: @@ -2876,7 +2956,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) mach64_log("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); } else if (addr & 0x300) { - mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) + mach64_accel_write_fifo(mach64, addr & 0x3ff, val); + else + mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); } else switch (addr & 0x3ff) { case 0x00: @@ -3099,7 +3182,10 @@ mach64_ext_writew(uint32_t addr, uint16_t val, void *p) mach64_ext_writeb(addr, val, p); mach64_ext_writeb(addr + 1, val >> 8, p); } else if (addr & 0x300) { - mach64_queue(mach64, addr & 0x3fe, val, FIFO_WRITE_WORD); + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) + mach64_accel_write_fifo_w(mach64, addr & 0x3fe, val); + else + mach64_queue(mach64, addr & 0x3fe, val, FIFO_WRITE_WORD); } else switch (addr & 0x3fe) { default: @@ -3120,7 +3206,10 @@ mach64_ext_writel(uint32_t addr, uint32_t val, void *p) mach64_ext_writew(addr, val, p); mach64_ext_writew(addr + 2, val >> 16, p); } else if (addr & 0x300) { - mach64_queue(mach64, addr & 0x3fc, val, FIFO_WRITE_DWORD); + if (((mach64->crtc_gen_cntl >> 8) & 7) == BPP_24) + mach64_accel_write_fifo_l(mach64, addr & 0x3fc, val); + else + mach64_queue(mach64, addr & 0x3fc, val, FIFO_WRITE_DWORD); } else switch (addr & 0x3fc) { default: @@ -3134,7 +3223,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *p) { mach64_t *mach64 = (mach64_t *) p; - uint8_t ret; + uint8_t ret = 0xff; switch (port) { case 0x02ec: @@ -4210,9 +4299,8 @@ mach64_common_init(const device_t *info) mach64_io_set(mach64); - if (info->flags & DEVICE_PCI) { + if (info->flags & DEVICE_PCI) mach64->card = pci_add_card(PCI_ADD_VIDEO, mach64_pci_read, mach64_pci_write, mach64); - } mach64->pci_regs[PCI_REG_COMMAND] = 3; mach64->pci_regs[0x30] = 0x00; @@ -4252,7 +4340,7 @@ mach64gx_init(const device_t *info) mach64->type = MACH64_GX; mach64->pci = !!(info->flags & DEVICE_PCI); mach64->pci_id = (int) 'X' | ((int) 'G' << 8); - mach64->config_chip_id = 0x020000d7; + mach64->config_chip_id = 0x000000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/ if (info->flags & DEVICE_PCI) @@ -4282,10 +4370,7 @@ mach64vt2_init(const device_t *info) mach64_t *mach64 = mach64_common_init(info); svga_t *svga = &mach64->svga; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci); mach64->type = MACH64_VT2; mach64->pci = 1; @@ -4299,8 +4384,7 @@ mach64vt2_init(const device_t *info) rom_init(&mach64->bios_rom, BIOS_ROMVT2_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&mach64->bios_rom.mapping); + mem_mapping_disable(&mach64->bios_rom.mapping); svga->vblank_start = mach64_vblank_start; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c new file mode 100644 index 000000000..9c0cbb616 --- /dev/null +++ b/src/video/vid_ati_mach8.c @@ -0,0 +1,5566 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the 8514/A-compatible Mach8 and Mach32 graphics + * chips from ATI for the ISA/VLB/MCA/PCI buses. + * + * + * + * Authors: TheCollector1995. + * + * Copyright 2022-2023 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/mca.h> +#include <86box/pci.h> +#include <86box/rom.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/video.h> +#include <86box/i2c.h> +#include <86box/vid_ddc.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include <86box/vid_ati_eeprom.h> + +#define BIOS_MACH8_ROM_PATH "roms/video/mach8/BIOS.BIN" +#define BIOS_MACH32_ISA_ROM_PATH "roms/video/mach32/MACH32ISA.VBI" +#define BIOS_MACH32_VLB_ROM_PATH "roms/video/mach32/MACH32VLB.VBI" +#define BIOS_MACH32_PCI_ROM_PATH "roms/video/mach32/MACH32PCI.BIN" + +typedef struct mach_t { + ati_eeprom_t eeprom; + svga_t svga; + + rom_t bios_rom; + mem_mapping_t mmio_linear_mapping; + + int mca_bus; + int pci_bus; + int vlb_bus; + uint8_t regs[256]; + uint8_t pci_regs[256]; + uint8_t int_line; + int card; + int index; + + uint32_t memory; + + uint16_t config1; + uint16_t config2; + + uint8_t pos_regs[8]; + uint8_t cursor_col_0, cursor_col_1; + uint8_t ext_cur_col_0_r, ext_cur_col_1_r; + uint8_t ext_cur_col_0_g, ext_cur_col_1_g; + uint16_t cursor_offset_lo, cursor_offset_hi; + uint16_t cursor_x, cursor_y; + uint16_t misc; + uint16_t memory_aperture; + uint16_t local_cntl; + uint32_t linear_base; + uint8_t ap_size; + uint8_t bank_w, bank_r; + + struct { + uint8_t line_idx; + int16_t line_array[6]; + uint8_t patt_idx; + uint8_t patt_len; + uint8_t pix_trans[2]; + uint8_t eeprom_control; + uint16_t dest_x_end; + uint16_t dest_x_start; + uint16_t dest_y_end; + uint16_t src_x_end; + uint16_t src_x_start; + uint16_t src_x, src_y; + int16_t bres_count; + uint16_t clock_sel; + uint16_t crt_offset_lo; + uint16_t crt_offset_hi; + uint16_t dest_cmp_fn; + uint16_t dp_config; + uint16_t ext_ge_config; + uint16_t ge_offset_lo; + uint16_t ge_offset_hi; + uint16_t linedraw_opt; + uint16_t max_waitstates; + uint8_t patt_data_idx; + uint8_t patt_data[0x18]; + uint16_t scan_to_x; + uint16_t scratch0; + uint16_t scratch1; + uint16_t test; + uint16_t pattern; + uint8_t test2[2], test3[2]; + int src_y_dir; + int cmd_type; + int block_write_mono_pattern_enable; + int mono_pattern_enable; + int16_t cx_end_line, cy_end_line; + int16_t cx, cx_end, cy_end, dx, dx_end, dy_end; + int16_t dx_start, dy_start; + int16_t cy, sx_start, sx_end; + int16_t sx, x_count, xx_count, xxx_count; + int16_t sy, y_count; + int16_t err; + int16_t width, src_width; + int16_t height; + int poly_src, temp_cnt; + int stepx, stepy, src_stepx; + uint8_t color_pattern[16]; + uint8_t color_pattern_full[32]; + uint16_t color_pattern_word[8]; + int mono_pattern[8][8]; + uint32_t ge_offset; + uint32_t crt_offset; + uint32_t patt_len_reg; + int poly_fill; + uint16_t dst_clr_cmp_mask; + int clip_overrun; + int color_pattern_idx; + } accel; + + atomic_int force_busy, force_busy2; +} mach_t; + +static video_timings_t timing_gfxultra_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_mach32_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; +static video_timings_t timing_mach32_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 20, .read_w = 20, .read_l = 21 }; + + +static void mach_accel_outb(uint16_t port, uint8_t val, void *p); +static void mach_accel_outw(uint16_t port, uint16_t val, void *p); +static uint8_t mach_accel_inb(uint16_t port, void *p); +static uint16_t mach_accel_inw(uint16_t port, void *p); + +static void mach32_updatemapping(mach_t *mach); + +#ifdef ENABLE_MACH_LOG +int mach_do_log = ENABLE_MACH_LOG; + +static void +mach_log(const char *fmt, ...) +{ + va_list ap; + + if (mach_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define mach_log(fmt, ...) +#endif + +#define READ_PIXTRANS_BYTE_IO(cx, n, vgacore) \ + if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ + if (vgacore) { \ + if ((svga->bpp == 15) || (svga->bpp == 16)) \ + if (n == 0) \ + mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (svga->vram_mask >> 1)] & 0xff; \ + else \ + mach->accel.pix_trans[(n)] = vram_w[(dev->accel.dest + (cx) + (n)) & (svga->vram_mask >> 1)] >> 8; \ + else \ + mach->accel.pix_trans[(n)] = svga->vram[(dev->accel.dest + (cx) + (n)) & svga->vram_mask]; \ + } else \ + mach->accel.pix_trans[(n)] = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ + } + +#define READ_PIXTRANS_WORD(cx, n, vgacore) \ + if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ + if (vgacore) { \ + if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (svga->vram_mask >> 1)]; \ + } else { \ + temp = svga->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & svga->vram_mask]; \ + temp |= (svga->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & svga->vram_mask] << 8); \ + } \ + } else { \ + temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ + } else if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ + if ((svga->bpp == 8) || (svga->bpp == 24)) { \ + if (vgacore) { \ + temp = svga->vram[((dev->accel.dest) + (cx) + (n)) & svga->vram_mask]; \ + temp |= (svga->vram[((dev->accel.dest) + (cx) + (n + 1)) & svga->vram_mask] << 8); \ + } else { \ + temp = dev->vram[((dev->accel.dest) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.dest) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ + } else if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (svga->vram_mask >> 1)]; \ + } \ + } else if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { \ + if ((svga->bpp == 8) || (svga->bpp == 24)) { \ + if (vgacore) { \ + temp = svga->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & svga->vram_mask]; \ + temp |= (svga->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n + 1)) & svga->vram_mask] << 8); \ + } else { \ + temp = dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + } \ + } else if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + temp = vram_w[((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (cx) + (n)) & (svga->vram_mask >> 1)]; \ + } \ + } + +#define READ(addr, dat, vgacore) \ + if ((svga->bpp == 8) || (svga->bpp == 24)) \ + dat = vgacore ? (svga->vram[(addr) & (svga->vram_mask)]) : (dev->vram[(addr) & (dev->vram_mask)]); \ + else if ((svga->bpp == 15) || (svga->bpp == 16)) \ + dat = vram_w[(addr) & (svga->vram_mask >> 1)]; + +#define MIX(mixmode, dest_dat, src_dat) \ + { \ + switch ((mixmode) ? (dev->accel.frgd_mix & 0x1f) : (dev->accel.bkgd_mix & 0x1f)) { \ + case 0x00: \ + dest_dat = ~dest_dat; \ + break; \ + case 0x01: \ + dest_dat = 0; \ + break; \ + case 0x02: \ + dest_dat = ~0; \ + break; \ + case 0x03: \ + dest_dat = dest_dat; \ + break; \ + case 0x04: \ + dest_dat = ~src_dat; \ + break; \ + case 0x05: \ + dest_dat = src_dat ^ dest_dat; \ + break; \ + case 0x06: \ + dest_dat = ~(src_dat ^ dest_dat); \ + break; \ + case 0x07: \ + dest_dat = src_dat; \ + break; \ + case 0x08: \ + dest_dat = ~(src_dat & dest_dat); \ + break; \ + case 0x09: \ + dest_dat = ~src_dat | dest_dat; \ + break; \ + case 0x0a: \ + dest_dat = src_dat | ~dest_dat; \ + break; \ + case 0x0b: \ + dest_dat = src_dat | dest_dat; \ + break; \ + case 0x0c: \ + dest_dat = src_dat & dest_dat; \ + break; \ + case 0x0d: \ + dest_dat = src_dat & ~dest_dat; \ + break; \ + case 0x0e: \ + dest_dat = ~src_dat & dest_dat; \ + break; \ + case 0x0f: \ + dest_dat = ~(src_dat | dest_dat); \ + break; \ + case 0x10: \ + dest_dat = MIN(src_dat, dest_dat); \ + break; \ + case 0x11: \ + dest_dat = dest_dat - src_dat; \ + break; \ + case 0x12: \ + dest_dat = src_dat - dest_dat; \ + break; \ + case 0x13: \ + dest_dat = src_dat + dest_dat; \ + break; \ + case 0x14: \ + dest_dat = MAX(src_dat, dest_dat); \ + break; \ + case 0x15: \ + dest_dat = (dest_dat - src_dat) / 2; \ + break; \ + case 0x16: \ + dest_dat = (src_dat - dest_dat) / 2; \ + break; \ + case 0x17: \ + dest_dat = (dest_dat + src_dat) / 2; \ + break; \ + case 0x18: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x19: \ + dest_dat = MAX(0, (dest_dat - src_dat)); \ + break; \ + case 0x1a: \ + dest_dat = MAX(0, (src_dat - dest_dat)); \ + break; \ + case 0x1b: \ + dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + break; \ + case 0x1c: \ + dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + break; \ + case 0x1d: \ + dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + break; \ + case 0x1e: \ + dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + break; \ + case 0x1f: \ + dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + break; \ + } \ + } + + +#define WRITE(addr, dat, vgacore) \ + if ((svga->bpp == 8) || (svga->bpp == 24)) { \ + if (vgacore) { \ + svga->vram[((addr)) & (svga->vram_mask)] = dat; \ + svga->changedvram[(((addr)) & (svga->vram_mask)) >> 12] = changeframecount; \ + } else { \ + dev->vram[((addr)) & (dev->vram_mask)] = dat; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + } \ + } else if ((svga->bpp == 15) || (svga->bpp == 16)) { \ + vram_w[((addr)) & (svga->vram_mask >> 1)] = dat; \ + svga->changedvram[(((addr)) & (svga->vram_mask >> 1)) >> 11] = changeframecount; \ + } + + +static int +mach_pixel_write(mach_t *mach) +{ + if (mach->accel.dp_config & 1) + return 1; + + return 0; +} + +static int +mach_pixel_read(mach_t *mach) +{ + if (mach->accel.dp_config & 1) + return 0; + + return 1; +} + +static void +mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint32_t cpu_dat, mach_t *mach, ibm8514_t *dev, int len) +{ + svga_t *svga = &mach->svga; + int compare_mode; + int poly_src = 0; + uint16_t rd_mask = dev->accel.rd_mask; + uint16_t wrt_mask = dev->accel.wrt_mask; + uint16_t dest_cmp_clr = dev->accel.color_cmp; + int frgd_sel, bkgd_sel, mono_src; + int compare = 0; + uint16_t src_dat = 0, dest_dat = 0; + uint16_t old_dest_dat; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint16_t mix = 0; + int16_t clip_l = dev->accel.clip_left & 0x7ff; + int16_t clip_t = dev->accel.clip_top & 0x7ff; + int16_t clip_r = dev->accel.multifunc[4] & 0x7ff; + int16_t clip_b = dev->accel.multifunc[3] & 0x7ff; + uint32_t mono_dat0 = 0, mono_dat1 = 0; + + if ((svga->bpp == 8) || (svga->bpp == 24)) { + rd_mask &= 0xff; + dest_cmp_clr &= 0xff; + } + + compare_mode = (mach->accel.dest_cmp_fn >> 3) & 7; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + mach->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + mach->force_busy = 1; + mach->force_busy2 = 1; + dev->force_busy = 1; + dev->force_busy2 = 1; + } + + if (cpu_input) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + if ((mach->accel.dp_config & 0x200) && (count == 2)) { + count >>= 1; + } + } + } + + if ((svga->bpp == 8) || (svga->bpp == 15) || (svga->bpp == 16) || (svga->bpp == 24)) { + if (svga->bpp == 24) + mach_log("24BPP: CMDType=%d, cwh(%d,%d,%d,%d), dpconfig=%04x\n", cmd_type, clip_l, clip_r, clip_t, clip_b, mach->accel.dp_config); + else + mach_log("BPP=%d, CMDType = %d, offs=%08x, DPCONFIG = %04x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, dstx = %d, dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", svga->bpp, cmd_type, mach->accel.ge_offset, mach->accel.dp_config, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + } + + switch (cmd_type) { + case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ + if (!cpu_input) { + dev->accel.dx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.dx |= ~0x5ff; + dev->accel.dy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.dy |= ~0x5ff; + + dev->accel.cx = dev->accel.destx_distp; + if (dev->accel.destx_distp >= 0x600) + dev->accel.cx |= ~0x5ff; + dev->accel.cy = dev->accel.desty_axstp; + if (dev->accel.desty_axstp >= 0x600) + dev->accel.cy |= ~0x5ff; + + mach->accel.width = mach->accel.bres_count; + dev->accel.sx = 0; + mach->accel.poly_fill = 0; + + mach->accel.color_pattern_idx = ((dev->accel.cx + (dev->accel.cy << 3)) & mach->accel.patt_len); + + mach->accel.stepx = (mach->accel.linedraw_opt & 0x20) ? 1 : -1; + mach->accel.stepy = (mach->accel.linedraw_opt & 0x80) ? 1 : -1; + + mach_log("Extended bresenham, CUR(%d,%d), DEST(%d,%d), width = %d, options = %04x, dpconfig = %04x, opt_ena = %03x.\n", dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.linedraw_opt, mach->accel.dp_config, mach->accel.max_waitstates & 0x100); + + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (mach_pixel_write(mach)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; + } else if (mach_pixel_read(mach)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + } + + if (frgd_sel == 5) { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x & mach->accel.patt_len]; + } + + /*The destination coordinates should match the pattern index.*/ + if (mach->accel.color_pattern_idx != mach->accel.patt_idx) + mach->accel.color_pattern_idx = mach->accel.patt_idx; + } + + if (mono_src == 1) { + count = mach->accel.width; + mix_dat = mach->accel.patt_data[0x10]; + dev->accel.temp_cnt = 8; + } + + if (mach->accel.linedraw_opt & 0x08) { /*Vector Line*/ + while (count--) { + switch (mono_src) { + case 0: + mix = 1; + break; + case 1: + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + case 3: + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } + mix = (mix & rd_mask) == rd_mask; + break; + } + + if ((((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b))) { + if (mach->accel.linedraw_opt & 0x02) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src, dev->local); + } + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + + if (!mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + } else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + } + } + + if ((mono_src == 1) && !count) + break; + else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + switch (mach->accel.linedraw_opt & 0xe0) { + case 0x00: + dev->accel.cx++; + dev->accel.dx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.dx++; + dev->accel.cy--; + dev->accel.dy--; + break; + case 0x40: + dev->accel.cy--; + dev->accel.dy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.dx--; + dev->accel.cy--; + dev->accel.dy--; + break; + case 0x80: + dev->accel.cx--; + dev->accel.dx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.dx--; + dev->accel.cy++; + dev->accel.dy++; + break; + case 0xc0: + dev->accel.cy++; + dev->accel.dy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.dx++; + dev->accel.cy++; + dev->accel.dy++; + break; + } + + dev->accel.sx++; + } + } else { /*Bresenham*/ + while (count--) { + switch (mono_src) { + case 0: + mix = 1; + break; + case 1: + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + case 3: + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } + mix = (mix & rd_mask) == rd_mask; + break; + } + + if ((((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b))) { + if (mach->accel.linedraw_opt & 0x02) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), poly_src, dev->local); + } + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + + if (!mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), mix, dev->local); + } + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.dx) + ((dev->accel.dy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + } else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.dy) * (dev->pitch)) + (dev->accel.dx), dest_dat, dev->local); + } + } + } + } + + if ((mono_src == 1) && !count) + break; + else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (mach->accel.linedraw_opt & 0x40) { + dev->accel.dy += mach->accel.stepy; + if ((frgd_sel == 3) || (bkgd_sel == 3)) + dev->accel.cy += mach->accel.stepy; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + dev->accel.dx += mach->accel.stepx; + if ((frgd_sel == 3) || (bkgd_sel == 3)) + dev->accel.cx += mach->accel.stepx; + } else { + dev->accel.err_term += dev->accel.desty_axstp; + } + } else { + dev->accel.dx += mach->accel.stepx; + if ((frgd_sel == 3) || (bkgd_sel == 3)) + dev->accel.cx += mach->accel.stepx; + + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + dev->accel.dy += mach->accel.stepy; + if ((frgd_sel == 3) || (bkgd_sel == 3)) + dev->accel.cy += mach->accel.stepy; + } else { + dev->accel.err_term += dev->accel.desty_axstp; + } + } + + dev->accel.sx++; + } + } + dev->accel.cur_x = dev->accel.dx; + dev->accel.cur_y = dev->accel.dy; + break; + + case 2: /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ + if (!cpu_input) { + mach->accel.stepx = 0; + mach->accel.stepy = 0; + + dev->accel.dx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.dx |= ~0x5ff; + + dev->accel.dy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.dy |= ~0x5ff; + + /*Destination Width*/ + if (mach->accel.dest_x_start != dev->accel.dx) + mach->accel.dest_x_start = dev->accel.dx; + + mach->accel.dx_start = mach->accel.dest_x_start; + if (mach->accel.dest_x_start >= 0x600) + mach->accel.dx_start |= ~0x5ff; + + mach->accel.dx_end = mach->accel.dest_x_end; + if (mach->accel.dest_x_end >= 0x600) + mach->accel.dx_end |= ~0x5ff; + + if (mach->accel.dx_end > mach->accel.dx_start) { + mach->accel.width = (mach->accel.dx_end - mach->accel.dx_start); + mach->accel.stepx = 1; + } else if (mach->accel.dx_end < mach->accel.dx_start) { + mach->accel.width = (mach->accel.dx_start - mach->accel.dx_end); + mach->accel.stepx = -1; + if (dev->accel.dx > 0) + dev->accel.dx--; + mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n", mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx, mach->accel.dp_config); + } else { + mach->accel.stepx = 1; + mach->accel.width = 0; + mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n", mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start); + } + + dev->accel.sx = 0; + mach->accel.poly_fill = 0; + mach->accel.color_pattern_idx = ((dev->accel.dx + (dev->accel.dy << 3)) & mach->accel.patt_len); + if ((svga->bpp == 24) && (mono_src != 1)) { + if (mach->accel.color_pattern_idx == mach->accel.patt_len) + mach->accel.color_pattern_idx = mach->accel.patt_data_idx; + } else if ((svga->bpp == 24) && (frgd_sel == 5) && (mono_src == 1) && (mach->accel.patt_len_reg & 0x4000)) + mach->accel.color_pattern_idx = 0; + + /*Height*/ + mach->accel.dy_start = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + mach->accel.dy_start |= ~0x5ff; + mach->accel.dy_end = mach->accel.dest_y_end; + if (mach->accel.dest_y_end >= 0x600) + mach->accel.dy_end |= ~0x5ff; + + if (mach->accel.dy_end > mach->accel.dy_start) { + mach->accel.height = (mach->accel.dy_end - mach->accel.dy_start); + mach->accel.stepy = 1; + } else if (mach->accel.dy_end < mach->accel.dy_start) { + mach->accel.height = (mach->accel.dy_start - mach->accel.dy_end); + mach->accel.stepy = -1; + } else { + mach->accel.height = 0; + mach->accel.stepy = 1; + } + + dev->accel.sy = 0; + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); + else + dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); + + mach->accel.src_stepx = 0; + + /*Source Width*/ + dev->accel.cx = mach->accel.src_x; + if (mach->accel.src_x >= 0x600) + dev->accel.cx |= ~0x5ff; + + dev->accel.cy = mach->accel.src_y; + if (mach->accel.src_y >= 0x600) + dev->accel.cy |= ~0x5ff; + + mach->accel.sx_start = mach->accel.src_x_start; + if (mach->accel.src_x_start >= 0x600) + mach->accel.sx_start |= ~0x5ff; + + mach->accel.sx_end = mach->accel.src_x_end; + if (mach->accel.src_x_end >= 0x600) + mach->accel.sx_end |= ~0x5ff; + + if (mach->accel.sx_end > mach->accel.sx_start) { + mach->accel.src_width = (mach->accel.sx_end - mach->accel.sx_start); + mach->accel.src_stepx = 1; + mach_log("BitBLT: Src Positive X: wh(%d,%d), srcwidth = %d, coordinates: %d,%d px, start: %d, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_start, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + } else if (mach->accel.sx_end < mach->accel.sx_start) { + mach->accel.src_width = (mach->accel.sx_start - mach->accel.sx_end); + mach->accel.src_stepx = -1; + if (dev->accel.cx > 0) + dev->accel.cx--; + mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + } else { + mach->accel.src_stepx = 1; + mach->accel.src_width = 0; + mach_log("BitBLT: Src Indeterminate X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + } + mach->accel.sx = 0; + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); + else + dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + + if ((svga->bpp == 24) && (frgd_sel == 5)) { + mach_log("BitBLT=%04x, WH(%d,%d), SRCWidth=%d, c(%d,%d), s(%d,%d).\n", mach->accel.dp_config, mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy); + } else + mach_log("BitBLT=%04x, Pitch=%d, C(%d,%d), SRCWidth=%d, WH(%d,%d), geoffset=%08x.\n", mach->accel.dp_config, dev->ext_pitch, dev->accel.cx, dev->accel.cy, mach->accel.src_width, mach->accel.width, mach->accel.height, (mach->accel.ge_offset << 2)); + + if (mono_src == 1) { + if ((mach->accel.mono_pattern_enable) && !(mach->accel.patt_len_reg & 0x4000)) { + mono_dat0 = mach->accel.patt_data[0x10]; + mono_dat0 |= (mach->accel.patt_data[0x11] << 8); + mono_dat0 |= (mach->accel.patt_data[0x12] << 16); + mono_dat0 |= (mach->accel.patt_data[0x13] << 24); + mono_dat1 = mach->accel.patt_data[0x14]; + mono_dat1 |= (mach->accel.patt_data[0x15] << 8); + mono_dat1 |= (mach->accel.patt_data[0x16] << 16); + mono_dat1 |= (mach->accel.patt_data[0x17] << 24); + + for (uint8_t y = 0; y < 8; y++) { + for (uint8_t x = 0; x < 8; x++) { + uint32_t temp = (y & 4) ? mono_dat1 : mono_dat0; + mach->accel.mono_pattern[y][7 - x] = (temp >> (x + ((y & 3) << 3))) & 1; + } + } + } + } + + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (mach_pixel_write(mach)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; + } else if (mach_pixel_read(mach)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + } + + if (mono_src == 1) { + if (!mach->accel.mono_pattern_enable && !(mach->accel.patt_len_reg & 0x4000)) { + count = mach->accel.width; + mix_dat = mach->accel.patt_data[0x10] ^ ((mach->accel.patt_idx & 1) ? 0xff : 0); + dev->accel.temp_cnt = 8; + } + } + + if (frgd_sel == 5) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + for (int x = 0; x <= mach->accel.patt_len; x += 2) { + mach->accel.color_pattern_word[x + (mach->accel.color_pattern_idx & 1)] = (mach->accel.patt_data[x & mach->accel.patt_len] & 0xff); + mach->accel.color_pattern_word[x + (mach->accel.color_pattern_idx & 1)] |= (mach->accel.patt_data[(x + 1) & mach->accel.patt_len] << 8); + } + } else { + if ((svga->bpp == 24) && (mach->accel.patt_len < 3)) { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x]; + mach_log("BITBLT: Color Pattern 24bpp[%d]=%02x, dataidx=%d, pattlen=%d.\n", x, mach->accel.color_pattern[x], mach->accel.patt_data_idx, mach->accel.patt_len); + } + } else { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x & mach->accel.patt_len]; + } + } + } + + /*The destination coordinates should match the pattern index.*/ + if (mach->accel.color_pattern_idx != mach->accel.patt_idx) + mach->accel.color_pattern_idx = mach->accel.patt_idx; + } + + if ((mach->accel.dy_end == mach->accel.dy_start)) { + mach_log("No DEST.\n"); + return; + } + + if ((mono_src == 3) || (bkgd_sel == 3) || (frgd_sel == 3)) { + if (mach->accel.sx_end == mach->accel.sx_start) { + mach_log("No SRC.\n"); + return; + } + } + + if (cpu_input) { + if (mach->accel.dp_config == 0x3251) { + if (dev->accel.sy == mach->accel.height) + return; + } + } + + while (count--) { + switch (mono_src) { + case 0: + mix = 1; + break; + case 1: + if (mach->accel.mono_pattern_enable) { + mix = mach->accel.mono_pattern[dev->accel.dy & 7][dev->accel.dx & 7]; + } else { + if ((svga->bpp == 24) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) + mix = 1; + else { + if (!dev->accel.temp_cnt) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + case 3: + READ(dev->accel.src + ((dev->accel.cx)), mix, dev->local); + mix = (mix & rd_mask) == rd_mask; + break; + } + + if (((dev->accel.dx) >= (clip_l) && (dev->accel.dx) <= (clip_r) && + (dev->accel.dy) >= (clip_t) && (dev->accel.dy) <= (clip_b))) { + if (mach->accel.dp_config & 0x02) { + READ(dev->accel.src + (dev->accel.cx), poly_src, dev->local); + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + + if (!mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + READ(dev->accel.src + (dev->accel.cx), src_dat, dev->local); + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + src_dat = mach->accel.color_pattern_word[mach->accel.color_pattern_idx]; + } else { + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + } + } else + src_dat = 0; + break; + } + } + + if ((svga->bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { + if (dev->accel.sy & 1) { + READ(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat, dev->local); + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat, dev->local); + } + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat, dev->local); + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if (mach->accel.dp_config & 0x10) { + if ((svga->bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && (mach->accel.patt_len_reg & 0x4000)) { + if (dev->accel.sy & 1) { + WRITE(dev->accel.dest + dev->accel.dx - dev->ext_pitch, dest_dat, dev->local); + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat, dev->local); + } + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat, dev->local); + } + } + } + + if ((svga->bpp == 8) || (svga->bpp == 24)) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3)) { + dev->accel.cx += mach->accel.src_stepx; + mach->accel.sx++; + if (mach->accel.sx >= mach->accel.src_width) { + mach->accel.sx = 0; + if (mach->accel.src_stepx == -1) + dev->accel.cx += mach->accel.src_width; + else + dev->accel.cx -= mach->accel.src_width; + dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); + else + dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + } + } + + dev->accel.dx += mach->accel.stepx; + + if ((svga->bpp == 8) || ((svga->bpp == 24) && (mach->accel.patt_len >= 3) && (mono_src != 1))) + mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; + + if ((svga->bpp == 24) && (mach->accel.color_pattern_idx == mach->accel.patt_len) && (mach->accel.patt_len >= 3) && (mono_src != 1)) { + mach->accel.color_pattern_idx = mach->accel.patt_data_idx; + } else if ((svga->bpp == 24) && (mach->accel.patt_len < 3)) { + if (mach->accel.patt_len == 2) { + mach->accel.color_pattern_idx++; + if (mach->accel.color_pattern_idx == 3) + mach->accel.color_pattern_idx = 0; + } else { + mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; + } + } else if ((svga->bpp == 24) && (mach->accel.patt_len_reg & 0x4000) && (frgd_sel == 5)) { + mach->accel.color_pattern_idx++; + if (mach->accel.color_pattern_idx == 3) + mach->accel.color_pattern_idx = 0; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; + mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; + } + + dev->accel.sx++; + if (dev->accel.sx >= mach->accel.width) { + mach->accel.poly_fill = 0; + dev->accel.sx = 0; + if (mach->accel.stepx == -1) + dev->accel.dx += mach->accel.width; + else + dev->accel.dx -= mach->accel.width; + + dev->accel.dy += mach->accel.stepy; + dev->accel.sy++; + + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); + else { + dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); + } + if ((mono_src == 1) && (svga->bpp == 24) && (frgd_sel == 5)) + mach->accel.color_pattern_idx = 0; + else + mach->accel.color_pattern_idx = ((dev->accel.dx + (dev->accel.dy << 3)) & mach->accel.patt_len); + + if ((svga->bpp == 24) && (mach->accel.color_pattern_idx == mach->accel.patt_len) && (mono_src != 1)) + mach->accel.color_pattern_idx = 0; + if ((mono_src == 1) && !mach->accel.mono_pattern_enable && !(mach->accel.patt_len_reg & 0x4000)) { + dev->accel.cur_x = dev->accel.dx; + dev->accel.cur_y = dev->accel.dy; + return; + } + if (dev->accel.sy >= mach->accel.height) { + if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 2) || (frgd_sel == 3) || (bkgd_sel == 2) || (bkgd_sel == 3)) + return; + if ((mono_src == 1) && (frgd_sel == 5) && (svga->bpp == 24) && (mach->accel.patt_len_reg & 0x4000)) + return; + dev->accel.cur_x = dev->accel.dx; + dev->accel.cur_y = dev->accel.dy; + return; + } + } + } + break; + + case 3: /*Direct Linedraw (Polyline) from linedraw indexes (0xfeee)*/ + case 4: + if (!cpu_input) { + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + + if (dev->accel.cur_x >= 0x600) { + mach_log("Linedraw XOver = %d.\n", dev->accel.cur_x); + dev->accel.cx |= ~0x5ff; + } + if (dev->accel.cur_y >= 0x600) { + mach_log("Linedraw YOver = %d.\n", dev->accel.cur_y); + dev->accel.cy |= ~0x5ff; + } + + dev->accel.dx = ABS(mach->accel.cx_end_line - dev->accel.cx) << 1; + dev->accel.dy = ABS(mach->accel.cy_end_line - dev->accel.cy) << 1; + + mach->accel.stepx = (mach->accel.cx_end_line < dev->accel.cx) ? -1 : 1; + mach->accel.stepy = (mach->accel.cy_end_line < dev->accel.cy) ? -1 : 1; + + dev->accel.sx = 0; + + mach_log("Linedraw: c(%d,%d), d(%d,%d), cend(%d,%d).\n", dev->accel.cur_x, dev->accel.cur_y, dev->accel.dx, dev->accel.dy, mach->accel.cx_end_line, mach->accel.cy_end_line); + + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (mach_pixel_write(mach)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; + } else if (mach_pixel_read(mach)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + } + + if (frgd_sel == 5) { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x & mach->accel.patt_len]; + } + } + + if (mono_src == 1) { + mix_dat = mach->accel.patt_data[0x10]; + dev->accel.temp_cnt = 8; + } + + count = (dev->accel.dx > dev->accel.dy) ? (dev->accel.dx >> 1) : (dev->accel.dy >> 1); + mach->accel.width = count; + + if (dev->accel.dx > dev->accel.dy) { + mach->accel.err = (dev->accel.dy - dev->accel.dx) >> 1; + if (mono_src == 1) { + while (count--) { + if (!dev->accel.temp_cnt) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + + if ((((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b))) { + mach->accel.clip_overrun = 0; + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + src_dat = 0; + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (!count) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (mach->accel.err >= 0) { + dev->accel.cy += mach->accel.stepy; + mach->accel.err -= dev->accel.dx; + } + dev->accel.cx += mach->accel.stepx; + mach->accel.err += dev->accel.dy; + } + } else { + while (count--) { + switch (mono_src) { + case 0: + case 3: + mix = 1; + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + } + + if ((((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b))) { + mach->accel.clip_overrun = 0; + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + src_dat = 0; + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (dev->accel.sx >= mach->accel.width) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (mach->accel.err >= 0) { + dev->accel.cy += mach->accel.stepy; + mach->accel.err -= dev->accel.dx; + } + dev->accel.cx += mach->accel.stepx; + mach->accel.err += dev->accel.dy; + + dev->accel.sx++; + } + } + } else { + mach->accel.err = (dev->accel.dx - dev->accel.dy) >> 1; + if (mono_src == 1) { + while (count--) { + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + + if ((((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b))) { + mach->accel.clip_overrun = 0; + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + src_dat = 0; + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (!count) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (mach->accel.err >= 0) { + dev->accel.cx += mach->accel.stepx; + mach->accel.err -= dev->accel.dy; + } + dev->accel.cy += mach->accel.stepy; + mach->accel.err += dev->accel.dx; + } + } else { + while (count--) { + switch (mono_src) { + case 0: + case 3: + mix = 1; + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + } + + if ((((dev->accel.cx) >= clip_l) && ((dev->accel.cx) <= clip_r) && ((dev->accel.cy) >= clip_t) && ((dev->accel.cy) <= clip_b))) { + mach->accel.clip_overrun = 0; + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + src_dat = 0; + } + break; + case 5: + if (mix) { + src_dat = mach->accel.color_pattern[((dev->accel.cx) + ((dev->accel.cy) << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) { + READ((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + READ((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } else { + if ((svga->bpp == 15) || (svga->bpp == 16)) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } else { + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat, dev->local); + } + } + } + } else + mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); + + if (dev->accel.sx >= mach->accel.width) + break; + + if (svga->bpp == 8) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + if (mach->accel.err >= 0) { + dev->accel.cx += mach->accel.stepx; + mach->accel.err -= dev->accel.dy; + } + dev->accel.cy += mach->accel.stepy; + mach->accel.err += dev->accel.dx; + + dev->accel.sx++; + } + } + } + mach->accel.line_array[(cmd_type == 4) ? 4 : 0] = dev->accel.cx; + mach->accel.line_array[(cmd_type == 4) ? 5 : 1] = dev->accel.cy; + dev->accel.cur_x = mach->accel.line_array[(cmd_type == 4) ? 4 : 0]; + dev->accel.cur_y = mach->accel.line_array[(cmd_type == 4) ? 5 : 1]; + break; + + case 5: /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ + if (!cpu_input) { + mach->accel.stepx = 0; + mach->accel.stepy = 0; + + dev->accel.dx = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + dev->accel.dx |= ~0x5ff; + dev->accel.dy = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + dev->accel.dy |= ~0x5ff; + + /*Destination Width*/ + mach->accel.dx_start = dev->accel.cur_x; + if (dev->accel.cur_x >= 0x600) + mach->accel.dx_start |= ~0x5ff; + mach->accel.dx_end = mach->accel.scan_to_x; + if (mach->accel.scan_to_x >= 0x600) + mach->accel.dx_end |= ~0x5ff; + + if (mach->accel.dx_end > mach->accel.dx_start) { + mach->accel.width = (mach->accel.dx_end - mach->accel.dx_start); + mach->accel.stepx = 1; + } else if (mach->accel.dx_end < mach->accel.dx_start) { + mach->accel.width = (mach->accel.dx_start - mach->accel.dx_end); + mach->accel.stepx = -1; + if (dev->accel.dx > 0) + dev->accel.dx--; + } else { + mach->accel.stepx = 1; + mach->accel.width = 0; + } + + dev->accel.sx = 0; + if ((svga->bpp == 24) && (mach->accel.patt_len < 0x17)) + mach->accel.color_pattern_idx = 0; + + /*Step Y*/ + mach->accel.dy_start = dev->accel.cur_y; + if (dev->accel.cur_y >= 0x600) + mach->accel.dy_start |= ~0x5ff; + mach->accel.dy_end = mach->accel.dest_y_end; + if (mach->accel.dest_y_end >= 0x600) + mach->accel.dy_end |= ~0x5ff; + + if (mach->accel.dy_end > mach->accel.dy_start) { + mach->accel.stepy = 1; + } else if (mach->accel.dy_end < mach->accel.dy_start) { + mach->accel.stepy = -1; + } else { + mach->accel.stepy = 0; + } + + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); + else + dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); + + mach->accel.src_stepx = 0; + + /*Source Width*/ + dev->accel.cx = mach->accel.src_x; + if (mach->accel.src_x >= 0x600) + dev->accel.cx |= ~0x5ff; + dev->accel.cy = mach->accel.src_y; + if (mach->accel.src_y >= 0x600) + dev->accel.cy |= ~0x5ff; + + mach->accel.sx_start = mach->accel.src_x_start; + if (mach->accel.src_x_start >= 0x600) + mach->accel.sx_start |= ~0x5ff; + + mach->accel.sx_end = mach->accel.src_x_end; + if (mach->accel.src_x_end >= 0x600) + mach->accel.sx_end |= ~0x5ff; + + if (mach->accel.sx_end > mach->accel.sx_start) { + mach->accel.src_width = (mach->accel.sx_end - mach->accel.sx_start); + mach->accel.src_stepx = 1; + } else if (mach->accel.sx_end < mach->accel.sx_start) { + mach->accel.src_width = (mach->accel.sx_start - mach->accel.sx_end); + mach->accel.src_stepx = -1; + if (dev->accel.cx > 0) + dev->accel.cx--; + } else { + mach->accel.src_stepx = 1; + mach->accel.src_width = 0; + } + + mach->accel.sx = 0; + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); + else + dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + + if ((svga->bpp == 24) && (frgd_sel == 5)) { + if (mach->accel.patt_len == 0x17) + mach->accel.color_pattern_idx = 0; + dev->accel.x1 = dev->accel.dx + mach->accel.width; + if (dev->accel.x1 == dev->pitch) { + dev->accel.x2 = mach->accel.width & 1; + } else if ((dev->accel.x1 == mach->accel.width) && (dev->accel.dy & 1) && !dev->accel.y1 && dev->accel.x2) { + if (mach->accel.patt_len == 0x17) + mach->accel.color_pattern_idx = 3; + dev->accel.x3 = 1; + } else + dev->accel.x3 = 0; + } else + mach_log("ScanToX=%04x, Pitch=%d, C(%d,%d), SRCWidth=%d, WH(%d,%d), geoffset=%08x.\n", mach->accel.dp_config, dev->ext_pitch, dev->accel.cx, dev->accel.cy, mach->accel.src_width, mach->accel.width, mach->accel.height, (mach->accel.ge_offset << 1)); + + dev->accel.y1 = 0; + + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { + if (mach_pixel_write(mach)) { + dev->data_available = 0; + dev->data_available2 = 0; + return; + } else if (mach_pixel_read(mach)) { + dev->data_available = 1; + dev->data_available2 = 1; + return; + } + } + } + + if (mono_src == 1) { + count = mach->accel.width; + mix_dat = mach->accel.patt_data[0x10]; + dev->accel.temp_cnt = 8; + } + + if (frgd_sel == 5) { + if (svga->bpp != 24) { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x & mach->accel.patt_len]; + } + } else { + if (mach->accel.patt_len == 0x17) { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern_full[x] = mach->accel.patt_data[x]; + mach_log("ScanToX: Color Pattern 24bpp[%d]=%02x, dataidx=%d, pattlen=%d.\n", x, mach->accel.color_pattern_full[x], mach->accel.patt_data_idx, mach->accel.patt_len); + } + } else { + for (int x = 0; x <= mach->accel.patt_len; x++) { + mach->accel.color_pattern[x] = mach->accel.patt_data[x]; + mach_log("ScanToX: Color Pattern 24bpp[%d]=%02x, dataidx=%d, pattlen=%d.\n", x, mach->accel.color_pattern[x], mach->accel.patt_data_idx, mach->accel.patt_len); + } + } + } + } + + while (count--) { + switch (mono_src) { + case 0: + mix = 1; + break; + case 1: + if (dev->accel.temp_cnt == 0) { + dev->accel.temp_cnt = 8; + mix_dat >>= 8; + } + mix = (mix_dat & 0x80); + dev->accel.temp_cnt--; + mix_dat <<= 1; + mix_dat |= 1; + break; + case 2: + if (mach->accel.dp_config & 0x1000) { + mix = mix_dat >> 0x1f; + mix_dat <<= 1; + } else { + if (mach->accel.dp_config & 0x200) { + mix = mix_dat & 1; + mix_dat >>= 1; + } else { + mix = mix_dat & 0x80; + mix_dat <<= 1; + mix_dat |= 1; + } + } + break; + case 3: + READ(dev->accel.src + (dev->accel.cx), mix, dev->local); + mix = (mix & rd_mask) == rd_mask; + break; + } + + if ((dev->accel.dx) >= (clip_l) && (dev->accel.dx) <= (clip_r) && + (dev->accel.dy) >= (clip_t) && (dev->accel.dy) <= (clip_b)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = dev->accel.bkgd_color; + break; + case 1: + src_dat = dev->accel.frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + if (mach_pixel_read(mach)) + src_dat = cpu_dat; + else { + READ(dev->accel.src + (dev->accel.cx), src_dat, dev->local); + if (mono_src == 3) { + src_dat = (src_dat & rd_mask) == rd_mask; + } + } + break; + case 5: + if (mix) { + if (svga->bpp == 24) { + if (mach->accel.patt_len == 0x17) + src_dat = mach->accel.color_pattern_full[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + } else + src_dat = mach->accel.color_pattern[(dev->accel.dx + (dev->accel.dy << 3)) & mach->accel.patt_len]; + } else + src_dat = 0; + break; + } + + READ(dev->accel.dest + (dev->accel.dx), dest_dat, dev->local); + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = ((dest_dat) >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = ((dest_dat) < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = ((dest_dat) != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = ((dest_dat) == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = ((dest_dat) <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = ((dest_dat) > dest_cmp_clr) ? 0 : 1; + break; + } + + if (!compare) { + if (mach_pixel_write(mach)) { + old_dest_dat = dest_dat; + MIX(mix, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + } + } + + if (mach->accel.dp_config & 0x10) { + WRITE(dev->accel.dest + (dev->accel.dx), dest_dat, dev->local); + } + } + + if ((svga->bpp == 8) || (svga->bpp == 24)) + cpu_dat >>= 8; + else + cpu_dat >>= 16; + + dev->accel.cx += mach->accel.src_stepx; + mach->accel.sx++; + if (mach->accel.sx >= mach->accel.src_width) { + mach->accel.sx = 0; + if (mach->accel.src_stepx == -1) { + dev->accel.cx += mach->accel.src_width; + } else + dev->accel.cx -= mach->accel.src_width; + dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.src = (mach->accel.ge_offset << 1) + (dev->accel.cy * (dev->pitch)); + else + dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); + } + + dev->accel.dx += mach->accel.stepx; + if ((svga->bpp == 24) && (mach->accel.patt_len == 0x17)) { + mach->accel.color_pattern_idx++; + if (dev->accel.x3) { + if (mach->accel.color_pattern_idx == 9) + mach->accel.color_pattern_idx = 3; + } else { + if (mach->accel.color_pattern_idx == 6) + mach->accel.color_pattern_idx = 0; + } + } else if ((svga->bpp == 24) && (mach->accel.patt_len < 3)) { + mach->accel.color_pattern_idx++; + if (mach->accel.color_pattern_idx == 3) + mach->accel.color_pattern_idx = 0; + } else + mach->accel.color_pattern_idx = (mach->accel.color_pattern_idx + mach->accel.stepx) & mach->accel.patt_len; + + dev->accel.sx++; + if (dev->accel.sx >= mach->accel.width) { + dev->accel.sx = 0; + dev->accel.dy += mach->accel.stepy; + if ((svga->bpp == 15) || (svga->bpp == 16)) + dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); + else + dev->accel.dest = (mach->accel.ge_offset << 2) + (dev->accel.dy * (dev->pitch)); + if (mach->accel.line_idx == 2) { + mach->accel.line_array[0] = dev->accel.dx; + mach->accel.line_array[4] = dev->accel.dx; + } + return; + } + } + break; + } +} + +static void +mach_accel_out_pixtrans(mach_t *mach, ibm8514_t *dev, uint16_t port, uint16_t val, uint16_t len) +{ + int frgd_sel, bkgd_sel, mono_src; + + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + if ((mach->accel.dp_config & 4) && (mach->accel.cmd_type != 5)) { + val = (val >> 8) | (val << 8); + } + + switch (mach->accel.dp_config & 0x200) { + case 0x000: /*8-bit size*/ + if ((mono_src == 2)) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if ((mach->accel.dp_config & 0x1000) && dev->local) + val = (val >> 8) | (val << 8); + mach_accel_start(mach->accel.cmd_type, 1, 8, val | (val << 16), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, val | (val << 16), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, val | (val << 16), mach, dev, len); + break; + case 0x200: /*16-bit size*/ + if ((mono_src == 2)) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if (mach->accel.dp_config & 0x1000) + val = (val >> 8) | (val << 8); + mach_accel_start(mach->accel.cmd_type, 1, 16, val | (val << 16), 0, mach, dev, len); + } else { + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev, len); + } + } else { + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, val | (val << 16), mach, dev, len); + } + break; + } +} + +static void +mach_out(uint16_t addr, uint8_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; + uint8_t old; + uint8_t rs2; + + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x1ce: + mach->index = val; + break; + case 0x1cf: + old = mach->regs[mach->index]; + mach->regs[mach->index] = val; + mach_log("ATI VGA write reg=0x%02X, val=0x%02X\n", mach->index, val); + switch (mach->index) { + case 0xa3: + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + break; + case 0xa7: + if ((old ^ val) & 0x80) + svga_recalctimings(svga); + break; + case 0xad: + if (dev->local) { + if ((old ^ val) & 0x0c) + svga_recalctimings(svga); + } + break; + case 0xb0: + if ((old ^ val) & 0x60) + svga_recalctimings(svga); + break; + case 0xae: + case 0xb2: + case 0xbe: + mach_log("ATI VGA write reg=0x%02X, val=0x%02X\n", mach->index, val); + if (mach->regs[0xbe] & 0x08) { /* Read/write bank mode */ + mach->bank_r = (((mach->regs[0xb2] & 1) << 3) | ((mach->regs[0xb2] & 0xe0) >> 5)); + mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); + if (dev->local) { + mach->bank_r |= (((mach->regs[0xae] & 0x0c) << 2)); + mach->bank_w |= (((mach->regs[0xae] & 3) << 4)); + } + if (ibm8514_on) + mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + } else { /* Single bank mode */ + mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); + if (dev->local) { + mach->bank_w |= (((mach->regs[0xae] & 3) << 4)); + } + mach->bank_r = mach->bank_w; + if (ibm8514_on) + mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + } + svga->read_bank = mach->bank_r << 16; + svga->write_bank = mach->bank_w << 16; + + if (mach->index == 0xbe) { + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + } + break; + case 0xbd: + if ((old ^ val) & 4) { + mach32_updatemapping(mach); + } + break; + case 0xb3: + ati_eeprom_write(&mach->eeprom, val & 8, val & 2, val & 1); + break; + case 0xb6: + if ((old ^ val) & 0x10) + svga_recalctimings(svga); + break; + case 0xb8: + if (dev->local) { + if ((old ^ val) & 0x40) + svga_recalctimings(svga); + } else { + if ((old ^ val) & 0xc0) + svga_recalctimings(svga); + } + break; + case 0xb9: + if ((old ^ val) & 2) + svga_recalctimings(svga); + break; + } + break; + + case 0x2ea: + case 0x2eb: + case 0x2ec: + case 0x2ed: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + if (dev->local) { + if (mach->pci_bus) + ati68860_ramdac_out((addr & 3) | (rs2 << 2), val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + } else + svga_out(addr, val, svga); + return; + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + if (dev->local) { + if (mach->pci_bus) + ati68860_ramdac_out((addr & 3) | (rs2 << 2), val, svga->ramdac, svga); + else + svga_out(addr, val, svga); + } else + svga_out(addr, val, svga); + return; + + case 0x3CF: + if (svga->gdcaddr == 6) { + uint8_t old_val = svga->gdcreg[6]; + svga->gdcreg[6] = val; + if ((svga->gdcreg[6] & 0xc) != (old_val & 0xc)) + mach32_updatemapping(mach); + return; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + if (old != val) { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { + svga->fullchange = 3; + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + } + svga_out(addr, val, svga); +} + +static uint8_t +mach_in(uint16_t addr, void *p) +{ + mach_t *mach = (mach_t *) p; + svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; + uint8_t temp; + uint8_t rs2; + + if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x1ce: + temp = mach->index; + break; + case 0x1cf: + switch (mach->index) { + case 0xa8: + temp = (svga->vc >> 8) & 3; + break; + case 0xa9: + temp = svga->vc & 0xff; + break; + case 0xb0: + temp = mach->regs[0xb0] | 0x80; + if (dev->local) { /*Mach32 VGA 1MB memory*/ + temp |= 0x08; + temp &= ~0x10; + } else { /*ATI 28800 VGA 512kB memory*/ + temp &= ~0x08; + temp |= 0x10; + } + break; + case 0xb7: + temp = mach->regs[0xb7] & ~8; + if (ati_eeprom_read(&mach->eeprom)) + temp |= 8; + break; + + default: + temp = mach->regs[mach->index]; + break; + } + break; + + case 0x2ea: + case 0x2eb: + case 0x2ec: + case 0x2ed: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + if (dev->local) { + if (mach->pci_bus) + return ati68860_ramdac_in((addr & 3) | (rs2 << 2), svga->ramdac, svga); + else + return svga_in(addr, svga); + } + return svga_in(addr, svga); + + case 0x3C6: + case 0x3C7: + case 0x3C8: + case 0x3C9: + rs2 = !!(mach->accel.ext_ge_config & 0x1000); + if (dev->local) { + if (mach->pci_bus) + return ati68860_ramdac_in((addr & 3) | (rs2 << 2), svga->ramdac, svga); + else + return svga_in(addr, svga); + } + return svga_in(addr, svga); + + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg]; + break; + case 0x3DA: + svga->attrff = 0; + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x38; + else + svga->cgastat ^= 0x38; + return svga->cgastat; + + default: + temp = svga_in(addr, svga); + break; + } + return temp; +} + +static void +mach_recalctimings(svga_t *svga) +{ + mach_t *mach = (mach_t *) svga->p; + ibm8514_t *dev = &svga->dev8514; + + if (vga_on && !ibm8514_on) { + switch (((mach->regs[0xbe] & 0x10) >> 1) | ((mach->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0c) >> 2)) { + case 0x00: + svga->clock = (cpuclock * (double) (1ull << 32)) / 42954000.0; + break; + case 0x01: + svga->clock = (cpuclock * (double) (1ull << 32)) / 48771000.0; + break; + case 0x02: + mach_log("clock 2\n"); + break; + case 0x03: + svga->clock = (cpuclock * (double) (1ull << 32)) / 36000000.0; + break; + case 0x04: + svga->clock = (cpuclock * (double) (1ull << 32)) / 50350000.0; + break; + case 0x05: + svga->clock = (cpuclock * (double) (1ull << 32)) / 56640000.0; + break; + case 0x06: + mach_log("clock 2\n"); + break; + case 0x07: + svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; + break; + case 0x08: + svga->clock = (cpuclock * (double) (1ull << 32)) / 30240000.0; + break; + case 0x09: + svga->clock = (cpuclock * (double) (1ull << 32)) / 32000000.0; + break; + case 0x0A: + svga->clock = (cpuclock * (double) (1ull << 32)) / 37500000.0; + break; + case 0x0B: + svga->clock = (cpuclock * (double) (1ull << 32)) / 39000000.0; + break; + case 0x0C: + svga->clock = (cpuclock * (double) (1ull << 32)) / 50350000.0; + break; + case 0x0D: + svga->clock = (cpuclock * (double) (1ull << 32)) / 56644000.0; + break; + case 0x0E: + svga->clock = (cpuclock * (double) (1ull << 32)) / 75000000.0; + break; + case 0x0F: + svga->clock = (cpuclock * (double) (1ull << 32)) / 65000000.0; + break; + default: + break; + } + } + + if (mach->regs[0xa3] & 0x10) + svga->ma_latch |= 0x10000; + + if (mach->regs[0xb0] & 0x40) + svga->ma_latch |= 0x20000; + + if (dev->local) { + if (mach->regs[0xad] & 0x04) + svga->ma_latch |= 0x40000; + + if (mach->regs[0xad] & 0x08) + svga->ma_latch |= 0x80000; + + if (mach->regs[0xb8] & 0x40) + svga->clock *= 2; + } else { + switch (mach->regs[0xb8] & 0xc0) { + case 0x40: + svga->clock *= 2; + break; + case 0x80: + svga->clock *= 3; + break; + case 0xc0: + svga->clock *= 4; + break; + } + } + + if (mach->regs[0xa7] & 0x80) + svga->clock *= 3; + + if (mach->regs[0xb6] & 0x10) { + svga->hdisp <<= 1; + svga->htotal <<= 1; + svga->rowoffset <<= 1; + svga->gdcreg[5] &= ~0x40; + } + + if (mach->regs[0xb0] & 0x20) { + svga->gdcreg[5] |= 0x40; + } + + if (vga_on && !ibm8514_on) { + if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { + if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: + case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + svga->map8 = svga->pallook; + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else { + svga->render = svga_render_8bpp_highres; + svga->ma_latch <<= 1; + svga->rowoffset <<= 1; + } + break; + + } + break; + } + } + } + } else if (dev->local) { + if (ibm8514_on) { + svga->hdisp_time = svga->hdisp = (dev->hdisp + 1) << 3; + dev->pitch = (dev->accel.advfunc_cntl & 4) ? 1024 : 640; + svga->htotal = (dev->htotal + 1); + svga->vtotal = (dev->vtotal + 1); + svga->vsyncstart = (dev->vsyncstart + 1); + svga->rowcount = !!(dev->disp_cntl & 0x08); + svga->dispend = ((dev->vdisp >> 1) + 1); + svga->interlace = dev->interlace; + svga->split = 0xffffff; + svga->vblankstart = svga->dispend; + + if (svga->dispend == 766) { + svga->dispend = 768; + svga->vblankstart = svga->dispend; + } + + if (svga->dispend == 598) { + svga->dispend = 600; + svga->vblankstart = svga->dispend; + } + + if (dev->accel.advfunc_cntl & 4) { + if (dev->ibm_mode) { + if (svga->hdisp == 8) { + svga->hdisp = 1024; + svga->dispend = 768; + svga->vtotal = 1536; + svga->vsyncstart = 1536; + } + } + + if (svga->interlace) { + svga->dispend >>= 1; + svga->vsyncstart >>= 2; + svga->vtotal >>= 2; + } else { + svga->vsyncstart >>= 1; + svga->vtotal >>= 1; + } + + dev->pitch = dev->ext_pitch; + svga->rowoffset = dev->ext_crt_pitch; + + svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; + } else { + if (dev->ibm_mode) { + if ((svga->hdisp == 1024) && !dev->internal_pitch) { + svga->hdisp = 640; + svga->dispend = 480; + } + } + + if (svga->interlace) { + svga->dispend >>= 1; + svga->vsyncstart >>= 2; + svga->vtotal >>= 2; + } else { + svga->vsyncstart >>= 1; + svga->vtotal >>= 1; + } + + dev->pitch = dev->ext_pitch; + svga->rowoffset = dev->ext_crt_pitch; + + svga->clock = (cpuclock * (double) (1ull << 32)) / 25175000.0; + } + switch (svga->bpp) { + case 8: + default: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + break; + case 16: + svga->render = svga_render_16bpp_highres; + break; + case 24: + svga->render = svga_render_24bpp_highres; + break; + } + mach_log("BPP=%d, VRAM Mask=%08x, NormalPitch=%d, CRTPitch=%d, VSYNCSTART=%d, VTOTAL=%d, ROWCOUNT=%d, mode=%d, highres bit=%x, has_vga?=%d, override=%d.\n", svga->bpp, svga->vram_mask, dev->pitch, dev->ext_crt_pitch, svga->vsyncstart, svga->vtotal, svga->rowcount, dev->ibm_mode, dev->accel.advfunc_cntl & 4, ibm8514_has_vga, svga->override); + } + mach_log("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", svga->hdisp, svga->vtotal, svga->htotal, svga->dispend, svga->rowoffset, svga->split, svga->vsyncstart, svga->split); + } +} + +static void +mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, uint32_t val, int len) +{ + int frgd_sel, bkgd_sel, mono_src; + switch (port) { + case 0x82e8: + case 0xc2e8: + if (len == 1) { + dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; + } else { + dev->accel.cur_y = val & 0x7ff; + } + break; + case 0x82e9: + case 0xc2e9: + if (len == 1) { + dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); + } + break; + + case 0x86e8: + case 0xc6e8: + if (len == 1) { + dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; + } else { + dev->accel.cur_x = val & 0x7ff; + } + break; + case 0x86e9: + case 0xc6e9: + if (len == 1) { + dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); + } + break; + + case 0x8ae8: + case 0xcae8: + if (len == 1) + dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; + else { + mach->accel.src_y = val; + dev->accel.desty_axstp = val & 0x3fff; + if (val & 0x2000) + dev->accel.desty_axstp |= ~0x1fff; + } + break; + case 0x8ae9: + case 0xcae9: + if (len == 1) { + dev->accel.desty_axstp = (dev->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.desty_axstp |= ~0x1fff; + } + break; + + case 0x8ee8: + case 0xcee8: + if (len == 1) + dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; + else { + mach->accel.src_x = val; + dev->accel.destx_distp = val & 0x3fff; + if (val & 0x2000) + dev->accel.destx_distp |= ~0x1fff; + } + break; + case 0x8ee9: + case 0xcee9: + if (len == 1) { + dev->accel.destx_distp = (dev->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.destx_distp |= ~0x1fff; + } + break; + + case 0x92e8: + if (len != 1) + dev->test = val; + case 0xd2e8: + mach_log("92E8 = %04x\n", val); + if (len == 1) + dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; + else { + dev->accel.err_term = val & 0x3fff; + if (val & 0x2000) + dev->accel.err_term |= ~0x1fff; + } + break; + case 0x92e9: + case 0xd2e9: + if (len == 1) { + dev->accel.err_term = (dev->accel.err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + dev->accel.err_term |= ~0x1fff; + } + break; + + case 0x96e8: + case 0xd6e8: + if (len == 1) + dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0x0700) | val; + else { + mach->accel.test = val & 0x1fff; + dev->accel.maj_axis_pcnt = val & 0x07ff; + } + break; + case 0x96e9: + case 0xd6e9: + if (len == 1) { + dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0xff) | ((val & 0x07) << 8); + } + break; + + case 0x9ae8: + case 0xdae8: + dev->accel.ssv_state = 0; + if (len == 1) + dev->accel.cmd = (dev->accel.cmd & 0xff00) | val; + else { + dev->data_available = 0; + dev->data_available2 = 0; + dev->accel.cmd = val; + mach_log("CMD8514 = %04x.\n", val); + mach->accel.cmd_type = -1; + if (port == 0xdae8) { + if (dev->accel.cmd & 0x100) + dev->accel.cmd_back = 0; + } + ibm8514_accel_start(-1, 0, -1, 0, svga, len); + } + break; + case 0x9ae9: + case 0xdae9: + if (len == 1) { + dev->data_available = 0; + dev->data_available2 = 0; + dev->accel.cmd = (dev->accel.cmd & 0xff) | (val << 8); + mach->accel.cmd_type = -1; + if (port == 0xdae9) { + if (dev->accel.cmd & 0x100) + dev->accel.cmd_back = 0; + } + ibm8514_accel_start(-1, 0, -1, 0, svga, len); + } + break; + + case 0x9ee8: + case 0xdee8: + dev->accel.ssv_state = 1; + if (len == 1) + dev->accel.short_stroke = (dev->accel.short_stroke & 0xff00) | val; + else { + dev->accel.short_stroke = val; + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + + if (dev->accel.cur_x >= 0x600) { + dev->accel.cx |= ~0x5ff; + } + if (dev->accel.cur_y >= 0x600) { + dev->accel.cy |= ~0x5ff; + } + + if (dev->accel.cmd & 0x1000) { + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + } else { + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + } + } + break; + case 0x9ee9: + case 0xdee9: + if (len == 1) { + dev->accel.short_stroke = (dev->accel.short_stroke & 0xff) | (val << 8); + dev->accel.cx = dev->accel.cur_x; + dev->accel.cy = dev->accel.cur_y; + + if (dev->accel.cur_x >= 0x600) { + dev->accel.cx |= ~0x5ff; + } + if (dev->accel.cur_y >= 0x600) { + dev->accel.cy |= ~0x5ff; + } + + if (dev->accel.cmd & 0x1000) { + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + } else { + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + } + } + break; + + case 0xa2e8: + case 0xe2e8: + if (port == 0xe2e8) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0x00ff) | val; + else + dev->accel.bkgd_color = val; + } else { + if (len == 1) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach->accel.pix_trans[1] = val; + } + } else { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach_accel_out_pixtrans(mach, dev, port, val, len); + } else { + if (ibm8514_cpu_dest(svga)) + break; + ibm8514_accel_out_pixtrans(svga, port, val, len); + } + } + } + } else { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0x00ff) | val; + else + dev->accel.bkgd_color = val; + } + break; + case 0xa2e9: + case 0xe2e9: + if (port == 0xe2e9) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0xff00) | (val << 8); + } else { + if (len == 1) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach->accel.pix_trans[0] = val; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + switch (mach->accel.dp_config & 0x200) { + case 0x000: /*8-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + mach_accel_start(mach->accel.cmd_type, 1, 8, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + case 0x200: /*16-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if (mach->accel.dp_config & 0x1000) + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[1] | (mach->accel.pix_trans[0] << 8), 0, mach, dev, len); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + } + } + } + } + } else { + if (len == 1) + dev->accel.bkgd_color = (dev->accel.bkgd_color & 0xff00) | (val << 8); + } + break; + + case 0xa6e8: + case 0xe6e8: + if (port == 0xe6e8) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0x00ff) | val; + else + dev->accel.frgd_color = val; + } else { + if (len == 1) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach->accel.pix_trans[1] = val; + } + } else { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach_accel_out_pixtrans(mach, dev, port, val, len); + } else { + if (ibm8514_cpu_dest(svga)) + break; + ibm8514_accel_out_pixtrans(svga, port, val, len); + } + } + } + } else { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0x00ff) | val; + else + dev->accel.frgd_color = val; + } + break; + case 0xa6e9: + case 0xe6e9: + if (port == 0xe6e9) { + if (dev->accel.cmd_back) { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0xff00) | (val << 8); + } else { + if (len == 1) { + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) + break; + mach->accel.pix_trans[0] = val; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + switch (mach->accel.dp_config & 0x200) { + case 0x000: /*8-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + mach_accel_start(mach->accel.cmd_type, 1, 8, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + case 0x200: /*16-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if (mach->accel.dp_config & 0x1000) + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[1] | (mach->accel.pix_trans[0] << 8), 0, mach, dev, len); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + } + } + } + } + } else { + if (len == 1) + dev->accel.frgd_color = (dev->accel.frgd_color & 0xff00) | (val << 8); + } + break; + + case 0xaae8: + case 0xeae8: + if (len == 1) + dev->accel.wrt_mask = (dev->accel.wrt_mask & 0x00ff) | val; + else + dev->accel.wrt_mask = val; + break; + case 0xaae9: + case 0xeae9: + if (len == 1) + dev->accel.wrt_mask = (dev->accel.wrt_mask & 0xff00) | (val << 8); + break; + + case 0xaee8: + case 0xeee8: + if (len == 1) + dev->accel.rd_mask = (dev->accel.rd_mask & 0x00ff) | val; + else + dev->accel.rd_mask = val; + break; + case 0xaee9: + case 0xeee9: + if (len == 1) + dev->accel.rd_mask = (dev->accel.rd_mask & 0xff00) | (val << 8); + break; + + case 0xb2e8: + case 0xf2e8: + if (len == 1) + dev->accel.color_cmp = (dev->accel.color_cmp & 0x00ff) | val; + else + dev->accel.color_cmp = val; + break; + case 0xb2e9: + case 0xf2e9: + if (len == 1) + dev->accel.color_cmp = (dev->accel.color_cmp & 0xff00) | (val << 8); + break; + + case 0xb6e8: + case 0xf6e8: + dev->accel.bkgd_mix = val & 0xff; + break; + + case 0xbae8: + case 0xfae8: + dev->accel.frgd_mix = val & 0xff; + break; + + case 0xbee8: + case 0xfee8: + if (len == 1) + dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff00) | val; + else { + dev->accel.multifunc_cntl = val; + dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if ((dev->accel.multifunc_cntl >> 12) == 1) { + dev->accel.clip_top = val & 0x7ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 2) { + dev->accel.clip_left = val & 0x7ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 3) { + dev->accel.multifunc[3] = val & 0x7ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 4) { + dev->accel.multifunc[4] = val & 0x7ff; + } + mach_log("CLIPBOTTOM=%d, CLIPRIGHT=%d, bpp=%d, pitch=%d.\n", dev->accel.multifunc[3], dev->accel.multifunc[4], svga->bpp, dev->pitch); + if ((dev->accel.multifunc_cntl >> 12) == 5) { + if (!dev->local || !dev->ext_crt_pitch) + dev->ext_crt_pitch = 128; + svga_recalctimings(svga); + } + if (port == 0xfee8) + dev->accel.cmd_back = 1; + else + dev->accel.cmd_back = 0; + } + break; + case 0xbee9: + case 0xfee9: + if (len == 1) { + dev->accel.multifunc_cntl = (dev->accel.multifunc_cntl & 0xff) | (val << 8); + dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; + if ((dev->accel.multifunc_cntl >> 12) == 1) { + dev->accel.clip_top = dev->accel.multifunc_cntl & 0x7ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 2) { + dev->accel.clip_left = dev->accel.multifunc_cntl & 0x7ff; + } + if ((dev->accel.multifunc_cntl >> 12) == 5) { + if (!dev->local || !dev->ext_crt_pitch) + dev->ext_crt_pitch = 128; + svga_recalctimings(svga); + } + if (port == 0xfee9) + dev->accel.cmd_back = 1; + else + dev->accel.cmd_back = 0; + } + break; + +/*ATI Mach8/32 specific registers*/ + case 0x82ee: + mach->accel.patt_data_idx = val & 0x1f; + mach_log("Pattern Data Index = %d.\n", val & 0x1f); + break; + + case 0x8eee: + if (len == 1) { + mach->accel.patt_data[mach->accel.patt_data_idx] = val; + } else { + mach->accel.patt_data[mach->accel.patt_data_idx] = val & 0xff; + mach->accel.patt_data[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; + if (mach->accel.mono_pattern_enable) + mach->accel.patt_data_idx = (mach->accel.patt_data_idx + 2) & 0x17; + else { + frgd_sel = (mach->accel.dp_config >> 13) & 7; + mono_src = (mach->accel.dp_config >> 5) & 3; + if ((svga->bpp == 24) && (mach->accel.patt_len == 0x17) && (frgd_sel == 5)) { + mach->accel.patt_data_idx += 2; + dev->accel.y1 = 1; + } else { + if (svga->bpp == 24) + mach->accel.patt_data_idx += 2; + else + mach->accel.patt_data_idx = (mach->accel.patt_data_idx + 2) & mach->accel.patt_len; + + } + mach_log("ExtCONFIG = %04x, Pattern Mono = %04x, selidx = %d, dataidx = %d, bit 0 = %02x len = %d.\n", mach->accel.ext_ge_config, val, mach->accel.patt_idx, mach->accel.patt_data_idx, val & 1, mach->accel.patt_len); + } + } + break; + case 0x8eef: + if (len == 1) { + mach->accel.patt_data[mach->accel.patt_data_idx + 1] = val; + if (mach->accel.mono_pattern_enable) + mach->accel.patt_data_idx = (mach->accel.patt_data_idx + 2) & 7; + else { + frgd_sel = (mach->accel.dp_config >> 13) & 7; + if ((svga->bpp == 24) && (mach->accel.patt_len == 0x17) && (frgd_sel == 5)) { + mach->accel.patt_data_idx += 2; + dev->accel.y1 = 1; + } else + mach->accel.patt_data_idx = (mach->accel.patt_data_idx + 2) & mach->accel.patt_len; + } + } + break; + + case 0x96ee: + if (len == 1) + mach->accel.bres_count = (mach->accel.bres_count & 0x700) | val; + else { + mach->accel.bres_count = val & 0x7ff; + mach_log("96EE line draw.\n"); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 1; + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + case 0x96ef: + if (len == 1) { + mach->accel.bres_count = (mach->accel.bres_count & 0xff) | ((val & 0x07) << 8); + mach_log("96EE (2) line draw.\n"); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 1; + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + + case 0x9aee: + mach->accel.line_idx = val & 0x07; + break; + + case 0xa2ee: + mach_log("Line OPT = %04x\n", val); + if (len == 1) + mach->accel.linedraw_opt = (mach->accel.linedraw_opt & 0xff00) | val; + else { + mach->accel.linedraw_opt = val; + } + break; + case 0xa2ef: + if (len == 1) { + mach->accel.linedraw_opt = (mach->accel.linedraw_opt & 0x00ff) | (val << 8); + } + break; + + case 0xa6ee: + if (len == 1) + mach->accel.dest_x_start = (mach->accel.dest_x_start & 0x700) | val; + else + mach->accel.dest_x_start = val & 0x7ff; + break; + case 0xa6ef: + if (len == 1) + mach->accel.dest_x_start = (mach->accel.dest_x_start & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xaaee: + if (len == 1) + mach->accel.dest_x_end = (mach->accel.dest_x_end & 0x700) | val; + else { + mach->accel.dest_x_end = val & 0x7ff; + } + break; + case 0xaaef: + if (len == 1) + mach->accel.dest_x_end = (mach->accel.dest_x_end & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xaeee: + mach_log("AEEE write val = %04x.\n", val); + if (len == 1) + mach->accel.dest_y_end = (mach->accel.dest_y_end & 0x700) | val; + else { + mach->accel.dest_y_end = val & 0x7ff; + if ((val + 1) == 0x10000) { + mach_log("Dest_Y_end overflow val = %04x\n", val); + mach->accel.dest_y_end = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach_log("BitBLT = %04x.\n", mach->accel.dp_config); + mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + case 0xaeef: + if (len == 1) { + mach->accel.dest_y_end = (mach->accel.dest_y_end & 0x0ff) | ((val & 0x07) << 8); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + + case 0xb2ee: + if (len == 1) + mach->accel.src_x_start = (mach->accel.src_x_start & 0x700) | val; + else + mach->accel.src_x_start = val & 0x7ff; + break; + case 0xb2ef: + if (len == 1) + mach->accel.src_x_start = (mach->accel.src_x_start & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xb6ee: + dev->accel.bkgd_mix = val & 0xff; + break; + + case 0xbaee: + dev->accel.frgd_mix = val & 0xff; + break; + + case 0xbeee: + if (len == 1) + mach->accel.src_x_end = (mach->accel.src_x_end & 0x700) | val; + else { + mach->accel.src_x_end = val & 0x7ff; + } + break; + case 0xbeef: + if (len == 1) + mach->accel.src_x_end = (mach->accel.src_x_end & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xc2ee: + mach->accel.src_y_dir = val & 1; + break; + + case 0xc6ee: + mach->accel.cmd_type = 0; + mach_log("TODO: Short Stroke.\n"); + break; + + case 0xcaee: + mach_log("CAEE write val = %04x.\n", val); + if (len == 1) + mach->accel.scan_to_x = (mach->accel.scan_to_x & 0x700) | val; + else { + mach->accel.scan_to_x = (val & 0x7ff); + if ((val + 1) == 0x10000) { + mach_log("Scan_to_X overflow val = %04x\n", val); + mach->accel.scan_to_x = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ + mach_log("ScanToX = %04x.\n", mach->accel.dp_config); + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + case 0xcaef: + if (len == 1) { + mach->accel.scan_to_x = (mach->accel.scan_to_x & 0x0ff) | ((val & 0x07) << 8); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + } + break; + + case 0xceee: + mach_log("CEEE write val = %04x.\n", val); + if (len == 1) + mach->accel.dp_config = (mach->accel.dp_config & 0xff00) | val; + else { + mach->accel.dp_config = val; + } + break; + case 0xceef: + if (len == 1) { + mach->accel.dp_config = (mach->accel.dp_config & 0x00ff) | (val << 8); + } + break; + + case 0xd2ee: + mach->accel.patt_len = val & 0x1f; + mach_log("Pattern Length = %d, val = %04x.\n", val & 0x1f, val); + mach->accel.mono_pattern_enable = !!(val & 0x80); + if (len != 1) { + mach->accel.patt_len_reg = val; + } else { + mach->accel.patt_len_reg = (mach->accel.patt_len_reg & 0xff00) | val; + } + break; + case 0xd2ef: + if (len == 1) + mach->accel.patt_len_reg = (mach->accel.patt_len_reg & 0x00ff) | (val << 8); + break; + + case 0xd6ee: + mach->accel.patt_idx = val & 0x1f; + mach_log("Pattern Index = %d, val = %02x.\n", val & 0x1f, val); + break; + + case 0xdaee: + mach_log("DAEE (extclipl) write val = %d\n", val); + if (len == 1) + dev->accel.clip_left = (dev->accel.clip_left & 0x700) | val; + else { + dev->accel.clip_left = val & 0x7ff; + } + break; + case 0xdaef: + if (len == 1) + dev->accel.clip_left = (dev->accel.clip_left & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xdeee: + mach_log("DEEE (extclipt) write val = %d\n", val); + if (len == 1) + dev->accel.clip_top = (dev->accel.clip_top & 0x700) | val; + else { + dev->accel.clip_top = val & 0x7ff; + } + break; + case 0xdeef: + if (len == 1) + dev->accel.clip_top = (dev->accel.clip_top & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xe2ee: + mach_log("E2EE (extclipr) write val = %d\n", val); + if (len == 1) + dev->accel.multifunc[4] = (dev->accel.multifunc[4] & 0x700) | val; + else { + dev->accel.multifunc[4] = val & 0x7ff; + } + break; + case 0xe2ef: + if (len == 1) + dev->accel.multifunc[4] = (dev->accel.multifunc[4] & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xe6ee: + mach_log("E6EE (extclipb) write val = %d\n", val); + if (len == 1) + dev->accel.multifunc[3] = (dev->accel.multifunc[3] & 0x700) | val; + else { + dev->accel.multifunc[3] = val & 0x7ff; + } + break; + case 0xe6ef: + if (len == 1) + dev->accel.multifunc[3] = (dev->accel.multifunc[3] & 0x0ff) | ((val & 0x07) << 8); + break; + + case 0xeeee: + if (len == 1) + mach->accel.dest_cmp_fn = (mach->accel.dest_cmp_fn & 0xff00) | val; + else + mach->accel.dest_cmp_fn = val; + break; + case 0xeeef: + if (len == 1) + mach->accel.dest_cmp_fn = (mach->accel.dest_cmp_fn & 0x00ff) | (val << 8); + break; + + case 0xf2ee: + mach_log("F2EE.\n"); + if (len == 1) + mach->accel.dst_clr_cmp_mask = (mach->accel.dst_clr_cmp_mask & 0xff00) | val; + else + mach->accel.dst_clr_cmp_mask = val; + break; + case 0xf2ef: + if (len == 1) + mach->accel.dst_clr_cmp_mask = (mach->accel.dst_clr_cmp_mask & 0x00ff) | (val << 8); + break; + + case 0xfeee: + if (mach->accel.dp_config == 0x2231 || mach->accel.dp_config == 0x2211) + mach_log("FEEE val = %d, lineidx = %d, DPCONFIG = %04x, CPUCX = %04x.\n", val, mach->accel.line_idx, mach->accel.dp_config, CX); + if (len != 1) { + mach->accel.line_array[mach->accel.line_idx] = val; + dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; + dev->accel.cur_y = mach->accel.line_array[(mach->accel.line_idx == 5) ? 5 : 1]; + mach->accel.cx_end_line = mach->accel.line_array[2]; + mach->accel.cy_end_line = mach->accel.line_array[3]; + if ((mach->accel.line_idx == 3) || (mach->accel.line_idx == 5)) { + mach->accel.cmd_type = (mach->accel.line_idx == 5) ? 4 : 3; + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, mach, dev, len); + mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; + break; + } + mach->accel.line_idx++; + } + break; + } +} + +static void +mach_accel_out(uint16_t port, uint32_t val, mach_t *mach, int len) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; + + mach_log("Port accel out = %04x, val = %04x, len = %d.\n", port, val, len); + + if (port & 0x8000) { + mach_accel_out_fifo(mach, svga, dev, port, val, len); + } else { + switch (port) { + case 0x2e8: + if (len == 1) + dev->htotal = (dev->htotal & 0xff00) | val; + else { + dev->htotal = val; + svga_recalctimings(svga); + } + break; + case 0x2e9: + if (len != 1) { + dev->htotal = (dev->htotal & 0xff) | (val << 8); + mach_log("ATI 8514/A: H_TOTAL write 02E8 = %d\n", dev->htotal + 1); + svga_recalctimings(svga); + } + break; + + case 0x6e8: + dev->hdisp = val; + mach_log("ATI 8514/A: H_DISP write 06E8 = %d\n", dev->hdisp + 1); + svga_recalctimings(svga); + break; + + case 0xae8: + mach_log("ATI 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + svga_recalctimings(svga); + break; + + case 0xee8: + mach_log("ATI 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); + svga_recalctimings(svga); + break; + + case 0x12e8: + if (len == 1) + dev->vtotal = (dev->vtotal & 0x1f00) | val; + else { + dev->vtotal = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x12e9: + if (len == 1) { + dev->vtotal = (dev->vtotal & 0xff) | ((val & 0x1f) << 8); + mach_log("ATI 8514/A: V_TOTAL write 12E8 = %d\n", dev->vtotal); + svga_recalctimings(svga); + } + break; + + case 0x16e8: + if (len == 1) + dev->vdisp = (dev->vdisp & 0x1f00) | val; + else { + dev->vdisp = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x16e9: + if (len == 1) { + dev->vdisp = (dev->vdisp & 0xff) | ((val & 0x1f) << 8); + mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); + svga_recalctimings(svga); + } + break; + + case 0x1ae8: + if (len == 1) + dev->vsyncstart = (dev->vsyncstart & 0x1f00) | val; + else { + dev->vsyncstart = val & 0x1fff; + svga_recalctimings(svga); + } + break; + case 0x1ae9: + if (len == 1) { + dev->vsyncstart = (dev->vsyncstart & 0xff) | ((val & 0x1f) << 8); + mach_log("ATI 8514/A: V_SYNC_STRT write 1AE8 = %d\n", dev->vsyncstart); + svga_recalctimings(svga); + } + break; + + case 0x1ee8: + dev->vsyncwidth = val; + mach_log("ATI 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); + svga_recalctimings(svga); + break; + + case 0x22e8: + dev->disp_cntl = val & 0x7e; + dev->interlace = !!(val & 0x10); + mach_log("ATI 8514/A: DISP_CNTL write 22E8 = %02x, SCANMODULOS = %d\n", dev->disp_cntl, dev->scanmodulos); + svga_recalctimings(svga); + break; + + case 0x42e8: + if (len == 1) { + dev->subsys_stat &= ~val; + } else { + dev->subsys_stat &= ~(val & 0xff); + dev->subsys_cntl = (val >> 8); + mach_log("CNTL = %02x.\n", val >> 8); + } + break; + case 0x42e9: + if (len == 1) { + dev->subsys_cntl = val; + mach_log("CNTL = %02x.\n", val); + } + break; + + case 0x4ae8: + mach_log("ATI 8514/A: VGA ON (0x4ae8) = %i, val = %02x\n", vga_on, val); + if (!val) + break; + if (!dev->local || !dev->ext_crt_pitch) + dev->ext_crt_pitch = 128; + dev->accel.advfunc_cntl = val & 7; + ibm8514_on = (dev->accel.advfunc_cntl & 1); + vga_on = !ibm8514_on; + dev->ibm_mode = 1; + if (ibm8514_on) + svga->adv_flags |= FLAG_ATI; + else + svga->adv_flags &= ~FLAG_ATI; + svga_recalctimings(svga); + break; + + /*ATI Mach8/32 specific registers*/ + case 0x6ee: + mach_log("6EE write val = %02x, len = %d.\n", val, len); + break; + + case 0x6ef: + mach_log("6EF write val = %02x, len = %d.\n", val, len); + break; + + case 0xaee: + if (len == 1) + mach->cursor_offset_lo = (mach->cursor_offset_lo & 0xff00) | val; + else { + mach_log("AEE val=%02x.\n", val); + mach->cursor_offset_lo = val; + svga->hwcursor.addr = mach->cursor_offset_lo << 2; + } + break; + case 0xaef: + if (len == 1) { + mach->cursor_offset_lo = (mach->cursor_offset_lo & 0x00ff) | (val << 8); + svga->hwcursor.addr = mach->cursor_offset_lo << 2; + } + break; + + case 0xeee: + mach->cursor_offset_hi = val & 0x0f; + if (len != 1) { + svga->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16))) << 2; + svga->hwcursor.ena = !!(val & 0x8000); + } + mach_log("EEE val=%08x.\n", svga->hwcursor.addr); + break; + case 0xeef: + if (len == 1) { + svga->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16))) << 2; + svga->hwcursor.ena = !!(val & 0x80); + } + break; + + case 0x12ee: + if (len == 1) { + svga->hwcursor.x = (svga->hwcursor.x & 0x700) | val; + } else { + svga->hwcursor.x = val & 0x7ff; + mach_log("X = %03x.\n", val); + } + break; + case 0x12ef: + if (len == 1) { + svga->hwcursor.x = (svga->hwcursor.x & 0x0ff) | ((val & 0x07) << 8); + } + break; + + case 0x16ee: + if (len == 1) { + svga->hwcursor.y = (svga->hwcursor.y & 0xf00) | val; + } else { + svga->hwcursor.y = val & 0xfff; + } + break; + case 0x16ef: + if (len == 1) { + svga->hwcursor.y = (svga->hwcursor.y & 0x0ff) | ((val & 0x0f) << 8); + } + break; + + case 0x1aee: + if (len != 1) { + mach->cursor_col_0 = val & 0xff; + mach->cursor_col_1 = (val >> 8) & 0xff; + } else + mach->cursor_col_0 = val; + break; + case 0x1aef: + if (len == 1) + mach->cursor_col_1 = val; + break; + + case 0x1eee: + if (len != 1) { + svga->hwcursor.xoff = val & 0x3f; + svga->hwcursor.yoff = (val >> 8) & 0x3f; + } else + svga->hwcursor.xoff = val & 0x3f; + break; + case 0x1eef: + if (len == 1) + svga->hwcursor.yoff = val & 0x3f; + break; + + case 0x2aee: + mach_log("2AEE write val = %04x\n", val); + if (len == 1) + mach->accel.crt_offset_lo = (mach->accel.crt_offset_lo & 0xff00) | val; + else + mach->accel.crt_offset_lo = val; + break; + case 0x2aef: + if (len == 1) + mach->accel.crt_offset_lo = (mach->accel.crt_offset_lo & 0x00ff) | (val << 8); + break; + + case 0x2eee: + mach_log("2EEE write val = %04x\n", val); + if (len == 1) + mach->accel.crt_offset_hi = (mach->accel.crt_offset_hi & 0xff00) | val; + else + mach->accel.crt_offset_hi = val; + break; + case 0x2eef: + if (len == 1) + mach->accel.crt_offset_hi = (mach->accel.crt_offset_hi & 0x00ff) | (val << 8); + break; + + case 0x26ee: + mach_log("CRT Pitch = %d, original val = %d.\n", val << 3, val); + dev->ext_crt_pitch = val; + dev->internal_pitch = val; + if (svga->bpp > 8) { + if (svga->bpp == 24) + dev->ext_crt_pitch *= 3; + else + dev->ext_crt_pitch <<= 1; + } + if (dev->local) { + if (!ibm8514_on) { + ibm8514_on ^= 1; + svga->adv_flags |= FLAG_ATI; + } + } + svga_recalctimings(svga); + break; + + case 0x32ee: + if (len == 1) { + mach->local_cntl = (mach->local_cntl & 0xff00) | val; + } else { + mach->local_cntl = val; + mach32_updatemapping(mach); + } + break; + + case 0x32ef: + if (len == 1) { + mach->local_cntl = (mach->local_cntl & 0x00ff) | (val << 8); + mach32_updatemapping(mach); + } + break; + + case 0x36ee: + if (len == 1) { + mach->misc = (mach->misc & 0xff00) | (val); + } else { + mach->misc = val; + } + break; + case 0x36ef: + if (len == 1) { + mach->misc = (mach->misc & 0x00ff) | (val << 8); + } + break; + + case 0x3aee: + if (len == 1) { + mach->ext_cur_col_0_g = val; + } else { + mach->ext_cur_col_0_g = val & 0xff; + mach->ext_cur_col_0_r = (val >> 8) & 0xff; + } + break; + case 0x3aef: + if (len == 1) { + mach->ext_cur_col_0_r = val; + } + break; + + case 0x3eee: + if (len == 1) { + mach->ext_cur_col_1_g = val; + } else { + mach->ext_cur_col_1_g = val & 0xff; + mach->ext_cur_col_1_r = (val >> 8) & 0xff; + } + break; + case 0x3eef: + if (len == 1) { + mach->ext_cur_col_1_r = val; + } + break; + + case 0x42ee: + mach->accel.test2[0] = val; + break; + case 0x42ef: + mach->accel.test2[1] = val; + break; + + case 0x46ee: + mach->accel.test3[0] = val; + break; + case 0x46ef: + mach->accel.test3[1] = val; + break; + + case 0x4aee: + if (len == 1) + mach->accel.clock_sel = (mach->accel.clock_sel & 0xff00) | val; + else { + mach->accel.clock_sel = val; + ibm8514_on = (mach->accel.clock_sel & 1); + vga_on = !ibm8514_on; + dev->ibm_mode = 0; + if (ibm8514_on) + svga->adv_flags |= FLAG_ATI; + else + svga->adv_flags &= ~FLAG_ATI; + mach_log("ATI 8514/A: VGA ON (0x4aee) = %i, val = %04x\n", vga_on, val); + svga_recalctimings(svga); + } + break; + case 0x4aef: + if (len == 1) { + mach->accel.clock_sel = (mach->accel.clock_sel & 0x00ff) | (val << 8); + ibm8514_on = (mach->accel.clock_sel & 1); + vga_on = !ibm8514_on; + dev->ibm_mode = 0; + if (ibm8514_on) + svga->adv_flags |= FLAG_ATI; + else + svga->adv_flags &= ~FLAG_ATI; + mach_log("ATI 8514/A: VGA ON (0x4aef) = %i, val = %04x\n", vga_on, mach->accel.clock_sel); + svga_recalctimings(svga); + } + break; + + case 0x52ee: + if (len == 1) + mach->accel.scratch0 = (mach->accel.scratch0 & 0xff00) | val; + else + mach->accel.scratch0 = val; + break; + case 0x52ef: + if (len == 1) + mach->accel.scratch0 = (mach->accel.scratch0 & 0x00ff) | (val << 8); + break; + + case 0x56ee: + if (len == 1) + mach->accel.scratch1 = (mach->accel.scratch1 & 0xff00) | val; + else + mach->accel.scratch1 = val; + break; + case 0x56ef: + if (len == 1) + mach->accel.scratch1 = (mach->accel.scratch1 & 0x00ff) | (val << 8); + break; + + case 0x5aee: + mach_log("Shadow set = %04x\n", val); + break; + case 0x5aef: + mach_log("Shadow + 1 set = %02x\n", val); + break; + + case 0x5eee: + mach_log("Memory Aperture = %04x, len = %d.\n", val, len); + if (len == 1) { + mach->memory_aperture = (mach->memory_aperture & 0xff00) | val; + } else { + mach->memory_aperture = val; + if (!mach->pci_bus) + mach->linear_base = (mach->memory_aperture & 0xff00) << 12; + + mach32_updatemapping(mach); + } + break; + + case 0x5eef: + if (len == 1) { + mach->memory_aperture = (mach->memory_aperture & 0x00ff) | (val << 8); + if (!mach->pci_bus) + mach->linear_base = (mach->memory_aperture & 0xff00) << 12; + + mach32_updatemapping(mach); + } + break; + + case 0x62ee: + mach_log("62EE write val = %04x, len = %d.\n", val, len); + break; + + case 0x66ee: + mach_log("66EE write val = %04x, len = %d.\n", val, len); + break; + + case 0x6aee: + mach_log("6AEE write val = %04x.\n", val & 0x400); + if (len == 1) + mach->accel.max_waitstates = (mach->accel.max_waitstates & 0xff00) | val; + else { + mach->accel.max_waitstates = val; + } + break; + case 0x6aef: + if (len == 1) + mach->accel.max_waitstates = (mach->accel.max_waitstates & 0x00ff) | (val << 8); + break; + + case 0x6eee: + mach_log("6EEE write val = %04x\n", val); + if (len == 1) + mach->accel.ge_offset_lo = (mach->accel.ge_offset_lo & 0xff00) | val; + else { + mach->accel.ge_offset_lo = val; + dev->accel.ge_offset = mach->accel.ge_offset_lo; + } + break; + case 0x6eef: + if (len == 1) { + mach->accel.ge_offset_lo = (mach->accel.ge_offset_lo & 0x00ff) | (val << 8); + dev->accel.ge_offset = mach->accel.ge_offset_lo; + } + break; + + case 0x72ee: + mach_log("72EE write val = %04x\n", val); + if (len == 1) + mach->accel.ge_offset_hi = (mach->accel.ge_offset_hi & 0xff00) | val; + else { + mach->accel.ge_offset_hi = val; + dev->accel.ge_offset = mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16); + } + break; + case 0x72ef: + if (len == 1) { + mach->accel.ge_offset_hi = (mach->accel.ge_offset_hi & 0x00ff) | (val << 8); + dev->accel.ge_offset = mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16); + } + break; + + case 0x76ee: + mach_log("76EE write val=%d shifted, normal=%d.\n", val << 3, val); + dev->ext_pitch = val << 3; + svga_recalctimings(svga); + break; + + case 0x7aee: + mach_log("7AEE write val = %04x, len = %d.\n", val, len); + if (len == 1) + mach->accel.ext_ge_config = (mach->accel.ext_ge_config & 0xff00) | val; + else { + mach->accel.ext_ge_config = val; + dev->ext_crt_pitch = dev->internal_pitch; + switch (mach->accel.ext_ge_config & 0x30) { + case 0: + case 0x10: + svga->bpp = 8; + break; + case 0x20: + if ((mach->accel.ext_ge_config & 0xc0) == 0x40) + svga->bpp = 16; + else + svga->bpp = 15; + + dev->ext_crt_pitch <<= 1; + break; + case 0x30: + svga->bpp = 24; + dev->ext_crt_pitch *= 3; + break; + } + if (mach->accel.ext_ge_config & 0x800) { + svga_recalctimings(svga); + } + if (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800)) + svga_recalctimings(svga); + } + break; + case 0x7aef: + mach_log("7AEF write val = %02x.\n", val); + if (len == 1) { + mach->accel.ext_ge_config = (mach->accel.ext_ge_config & 0x00ff) | (val << 8); + dev->ext_crt_pitch = dev->internal_pitch; + switch (mach->accel.ext_ge_config & 0x30) { + case 0: + case 0x10: + svga->bpp = 8; + break; + case 0x20: + if ((mach->accel.ext_ge_config & 0xc0) == 0x40) + svga->bpp = 16; + else + svga->bpp = 15; + + dev->ext_crt_pitch <<= 1; + break; + case 0x30: + svga->bpp = 24; + dev->ext_crt_pitch *= 3; + break; + } + if (mach->accel.ext_ge_config & 0x800) { + svga_recalctimings(svga); + } + if (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800)) + svga_recalctimings(svga); + } + break; + + case 0x7eee: + mach->accel.eeprom_control = val; + break; + } + } +} + +static uint32_t +mach_accel_in(uint16_t port, mach_t *mach, int len) +{ + svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; + uint16_t *vram_w = (uint16_t *) svga->vram; + uint16_t temp = 0; + int cmd; + int vpos = dev->displine + svga->y_add; + int vblankend = svga->vblankstart + svga->crtc[0x16]; + int frgd_sel, bkgd_sel, mono_src; + + switch (port) { + case 0x2e8: + if (dev->local) { + vpos = svga->displine + svga->y_add; + if (vblankend > svga->vtotal) { + vblankend -= svga->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + temp |= 2; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + temp |= 2; + } + } else { + vpos = dev->displine + svga->y_add; + if (vblankend > dev->vtotal) { + vblankend -= dev->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + temp |= 2; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + temp |= 2; + } + } + break; + + case 0x6e8: + temp = dev->hdisp; + break; + + case 0x22e8: + temp = dev->disp_cntl; + break; + + case 0x26e8: + if (len == 1) + temp = dev->htotal & 0xff; + else + temp = dev->htotal; + break; + case 0x26e9: + if (len == 1) + temp = dev->htotal >> 8; + break; + + case 0x2ee8: + temp = dev->subsys_cntl; + break; + + case 0x42e8: + if (dev->local) { + vpos = svga->displine + svga->y_add; + if (vblankend > svga->vtotal) { + vblankend -= svga->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + dev->subsys_stat |= 1; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + dev->subsys_stat |= 1; + } + } else { + vpos = dev->displine + svga->y_add; + if (vblankend > dev->vtotal) { + vblankend -= dev->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + dev->subsys_stat |= 1; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + dev->subsys_stat |= 1; + } + } + + if (len != 1) { + temp = dev->subsys_stat | 0xa0 | 0x8000; + } else { + temp = dev->subsys_stat | 0xa0; + } + break; + + case 0x4ae8: + temp = dev->accel.advfunc_cntl; + break; + + case 0x42e9: + if (len == 1) { + temp = dev->subsys_stat >> 8; + temp |= 0x80; + } + break; + + case 0x82e8: + case 0xc2e8: + if (len != 1) { + temp = dev->accel.cur_y; + } + break; + + case 0x86e8: + case 0xc6e8: + if (len != 1) { + temp = dev->accel.cur_x; + } + break; + + case 0x92e8: + if (len != 1) { + temp = dev->test; + } + break; + + case 0x96e8: + if (len != 1) { + temp = dev->accel.maj_axis_pcnt; + } + break; + + case 0x9ae8: + case 0xdae8: + if (len != 1) { + if (dev->force_busy) + temp |= 0x200; /*Hardware busy*/ + dev->force_busy = 0; + if (dev->data_available) { + temp |= 0x100; /*Read Data available*/ + if (mach->accel.cmd_type >= 0) { + switch (mach->accel.cmd_type) { + case 2: + if (dev->accel.sy >= mach->accel.height) + dev->data_available = 0; + break; + case 5: + if (dev->accel.sx >= mach->accel.width) + dev->data_available = 0; + break; + default: + if (dev->accel.sy < 0) + dev->data_available = 0; + break; + } + } else { + if (dev->accel.sy < 0) + dev->data_available = 0; + } + } + } + mach_log("[%04X:%08X]: 9AE8: Temp = %04x, len = %d\n\n", CS, cpu_state.pc, temp, len); + break; + case 0x9ae9: + case 0xdae9: + if (len == 1) { + if (dev->force_busy2) + temp |= 2; /*Hardware busy*/ + dev->force_busy2 = 0; + if (dev->data_available2) { + temp |= 1; /*Read Data available*/ + if (mach->accel.cmd_type >= 0) { + switch (mach->accel.cmd_type) { + case 2: + if (dev->accel.sy >= mach->accel.height) + dev->data_available2 = 0; + break; + case 5: + if (dev->accel.sx >= mach->accel.width) + dev->data_available2 = 0; + break; + default: + if (dev->accel.sy < 0) + dev->data_available2 = 0; + break; + } + } else { + if (dev->accel.sy < 0) + dev->data_available2 = 0; + } + } + } + mach_log("[%04X:%08X]: 9AE9: Temp = %04x, len = %d\n\n", CS, cpu_state.pc, temp, len); + break; + + case 0xe2e8: + case 0xe6e8: + if (mach->accel.cmd_type >= 0) { + if (mach_pixel_read(mach)) { + cmd = -1; + if (len == 1) { + READ_PIXTRANS_BYTE_IO(dev->accel.dx, 1, dev->local) + + temp = mach->accel.pix_trans[1]; + } else { + if (mach->accel.cmd_type == 3) { + READ_PIXTRANS_WORD(dev->accel.cx, 0, dev->local) + } else { + READ_PIXTRANS_WORD(dev->accel.dx, 0, dev->local) + } + mach_accel_out_pixtrans(mach, dev, port, temp, len); + } + } + } else { + if (ibm8514_cpu_dest(svga)) { + cmd = (dev->accel.cmd >> 13); + if (len == 1) { + ; // READ_PIXTRANS_BYTE_IO(0) + } else { + READ_PIXTRANS_WORD(dev->accel.cx, 0, dev->local) + if (dev->accel.input && !dev->accel.odd_in && !dev->accel.sx) { + temp &= ~0xff00; + if (dev->local) + temp |= (svga->vram[(dev->accel.newdest_in + dev->accel.cur_x) & svga->vram_mask] << 8); + else + temp |= (dev->vram[(dev->accel.newdest_in + dev->accel.cur_x) & dev->vram_mask] << 8); + } + if (dev->subsys_stat & 1) { + dev->force_busy = 1; + dev->data_available = 1; + } + } + ibm8514_accel_out_pixtrans(svga, port, temp, len); + } + } + break; + case 0xe2e9: + case 0xe6e9: + if (mach->accel.cmd_type >= 0) { + mach_log("%04x pixtrans read, len=%d.\n", port, len); + if (mach_pixel_read(mach)) { + if (len == 1) { + cmd = -1; + READ_PIXTRANS_BYTE_IO(dev->accel.dx, 0, dev->local) + + temp = mach->accel.pix_trans[0]; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + switch (mach->accel.dp_config & 0x200) { + case 0x000: /*8-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + mach_accel_start(mach->accel.cmd_type, 1, 8, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 1, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + case 0x200: /*16-bit size*/ + if (mono_src == 2) { + if ((frgd_sel != 2) && (bkgd_sel != 2)) { + if (mach->accel.dp_config & 0x1000) + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[1] | (mach->accel.pix_trans[0] << 8), 0, mach, dev, len); + else + mach_accel_start(mach->accel.cmd_type, 1, 16, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), 0, mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + } else + mach_accel_start(mach->accel.cmd_type, 1, 2, -1, mach->accel.pix_trans[0] | (mach->accel.pix_trans[1] << 8), mach, dev, len); + break; + } + } + } + } + break; + + case 0xbee8: + case 0xfee8: + if (len != 1) { + mach_log("Multifunc_cntl = %d.\n", dev->accel.multifunc_cntl >> 12); + switch ((dev->accel.multifunc_cntl >> 12) & 0x0f) { + case 0: + temp = dev->accel.multifunc[0]; + break; + case 1: + temp = dev->accel.clip_top; + break; + case 2: + temp = dev->accel.clip_left; + break; + case 3: + temp = dev->accel.multifunc[3]; + break; + case 4: + temp = dev->accel.multifunc[4]; + break; + case 5: + temp = dev->accel.multifunc[5]; + break; + case 8: + temp = dev->accel.multifunc[8]; + break; + case 9: + temp = dev->accel.multifunc[9]; + break; + case 0x0a: + temp = dev->accel.multifunc[0x0a]; + break; + } + } + break; + +/*ATI Mach8/32 specific registers*/ + case 0x12ee: + if (len == 1) + temp = mach->config1 & 0xff; + else + temp = mach->config1; + break; + case 0x12ef: + if (len == 1) + temp = mach->config1 >> 8; + break; + + case 0x16ee: + if (len == 1) + temp = mach->config2 & 0xff; + else + temp = mach->config2; + break; + case 0x16ef: + if (len == 1) + temp = mach->config2 >> 8; + break; + + case 0x32ee: + if (len == 1) + temp = mach->local_cntl & 0xff; + else + temp = mach->local_cntl; + break; + case 0x32ef: + if (len == 1) + temp = mach->local_cntl >> 8; + break; + + case 0x36ee: + if (len == 1) + temp = mach->misc & 0xff; + else + temp = mach->misc; + break; + case 0x36ef: + if (len == 1) + temp = mach->misc >> 8; + break; + + case 0x42ee: + temp = mach->accel.test2[0]; + break; + case 0x42ef: + temp = mach->accel.test2[1]; + break; + + case 0x46ee: + temp = mach->accel.test3[0]; + break; + case 0x46ef: + temp = mach->accel.test3[1]; + break; + + case 0x4aee: + if (len == 1) + temp = mach->accel.clock_sel & 0xff; + else + temp = mach->accel.clock_sel; + break; + case 0x4aef: + if (len == 1) + temp = mach->accel.clock_sel >> 8; + break; + + case 0x52ee: + if (len == 1) + temp = mach->accel.scratch0 & 0xff; + else + temp = mach->accel.scratch0; + break; + case 0x52ef: + if (len == 1) + temp = mach->accel.scratch0 >> 8; + break; + + case 0x56ee: + if (len == 1) + temp = mach->accel.scratch1 & 0xff; + else + temp = mach->accel.scratch1; + break; + case 0x56ef: + if (len == 1) + temp = mach->accel.scratch1 >> 8; + break; + + case 0x5eee: + if (mach->pci_bus) + mach->memory_aperture = (mach->memory_aperture & ~0xfff0) | ((mach->linear_base >> 20) << 4); + + if (len == 1) + temp = mach->memory_aperture & 0xff; + else + temp = mach->memory_aperture; + break; + case 0x5eef: + if (len == 1) + temp = mach->memory_aperture >> 8; + break; + + case 0x62ee: + temp = mach->accel.clip_overrun; + if (len != 1) { + if (mach->force_busy) + temp |= 0x2000; + mach->force_busy = 0; + if (ati_eeprom_read(&mach->eeprom)) + temp |= 0x4000; + } + mach_log("[%04X:%08X]: 62EE: Temp = %04x, len = %d\n\n", CS, cpu_state.pc, temp, len); + break; + case 0x62ef: + if (len == 1) { + if (mach->force_busy2) + temp |= 0x20; + mach->force_busy2 = 0; + if (ati_eeprom_read(&mach->eeprom)) + temp |= 0x40; + } + mach_log("[%04X:%08X]: 62EF: Temp = %04x, len = %d\n\n", CS, cpu_state.pc, temp, len); + break; + + case 0x6aee: + if (len == 1) + temp = mach->accel.max_waitstates & 0xff; + else + temp = mach->accel.max_waitstates; + break; + case 0x6aef: + if (len == 1) + temp = mach->accel.max_waitstates >> 8; + break; + + case 0x72ee: + if (len == 1) + temp = dev->accel.clip_left & 0xff; + else + temp = dev->accel.clip_left; + break; + case 0x72ef: + if (len == 1) + temp = dev->accel.clip_left >> 8; + break; + + case 0x76ee: + if (len == 1) + temp = dev->accel.clip_top & 0xff; + else + temp = dev->accel.clip_top; + break; + case 0x76ef: + if (len == 1) + temp = dev->accel.clip_top >> 8; + break; + + case 0x7aee: + if (len == 1) + temp = dev->accel.multifunc[4] & 0xff; + else + temp = dev->accel.multifunc[4]; + break; + case 0x7aef: + if (len == 1) + temp = dev->accel.multifunc[4] >> 8; + break; + + case 0x7eee: + if (len == 1) + temp = dev->accel.multifunc[3] & 0xff; + else + temp = dev->accel.multifunc[3]; + break; + case 0x7eef: + if (len == 1) + temp = dev->accel.multifunc[3] >> 8; + break; + + case 0x82ee: + temp = mach->accel.patt_data_idx; + break; + + case 0x8eee: + if (len == 1) + temp = mach->accel.ext_ge_config & 0xff; + else + temp = mach->accel.ext_ge_config; + break; + case 0x8eef: + if (len == 1) + temp = mach->accel.ext_ge_config >> 8; + break; + + case 0x92ee: + temp = mach->accel.eeprom_control; + break; + + case 0x96ee: + if (len == 1) { + temp = dev->accel.maj_axis_pcnt & 0xff; + } else { + temp = dev->accel.maj_axis_pcnt; + if ((mach->accel.test == 0x1555) || (mach->accel.test == 0x0aaa)) + temp = mach->accel.test; + } + break; + case 0x96ef: + if (len == 1) + temp = dev->accel.maj_axis_pcnt >> 8; + break; + + case 0xa2ee: + if (len == 1) + temp = mach->accel.linedraw_opt & 0xff; + else { + temp = mach->accel.linedraw_opt; + } + break; + case 0xa2ef: + if (len == 1) + temp = mach->accel.linedraw_opt >> 8; + break; + + case 0xb2ee: + if (len == 1) + temp = dev->hdisp; + else { + temp = dev->hdisp & 0xff; + temp |= (dev->htotal << 8); + mach_log("HDISP read=%d, HTOTAL read=%d.\n", temp & 0xff, temp >> 8); + } + break; + case 0xb2ef: + if (len == 1) { + temp = dev->htotal; + } + break; + + case 0xc2ee: + if (len == 1) + temp = dev->vtotal & 0xff; + else { + temp = dev->vtotal; + mach_log("VTOTAL read=%d.\n", temp); + } + break; + case 0xc2ef: + if (len == 1) + temp = dev->vtotal >> 8; + break; + + case 0xc6ee: + if (len == 1) + temp = dev->vdisp & 0xff; + else { + temp = dev->vdisp; + mach_log("VDISP read=%d.\n", temp); + } + break; + case 0xc6ef: + if (len == 1) + temp = dev->vdisp >> 8; + break; + + case 0xcaee: + if (len == 1) + temp = dev->vsyncstart & 0xff; + else + temp = dev->vsyncstart; + break; + case 0xcaef: + if (len == 1) + temp = dev->vsyncstart >> 8; + break; + + case 0xceee: + if (len == 1) + temp = svga->vc & 0xff; + else + temp = svga->vc & 0x7ff; + break; + case 0xceef: + if (len == 1) + temp = (svga->vc >> 8) & 7; + break; + + case 0xdaee: + if (len != 1) { + temp = mach->accel.src_x; + if (dev->local) { + temp &= 0x7ff; + } + } else + temp = dev->accel.destx_distp & 0xff; + break; + case 0xdaef: + if (len == 1) + temp = dev->accel.destx_distp >> 8; + break; + + case 0xdeee: + if (len != 1) { + temp = mach->accel.src_y; + if (dev->local) + temp &= 0x7ff; + } else + temp = dev->accel.desty_axstp & 0xff; + break; + case 0xdeef: + if (len == 1) + temp = dev->accel.desty_axstp >> 8; + break; + + case 0xfaee: + if (len != 1) { + if (mach->pci_bus) + temp = 0x0017; + else + temp = 0x22f7; + } else { + if (mach->pci_bus) + temp = 0x17; + else + temp = 0xf7; + } + break; + case 0xfaef: + if (len == 1) { + if (mach->pci_bus) + temp = 0x00; + else + temp = 0x22; + } + break; + } + if (port != 0x9ae8 && port != 0x9ae9 && port != 0x62ee && port != 0x9aee) { + mach_log("Port accel in = %04x, temp = %04x, len = %d, mode = %d.\n", port, temp, len, dev->ibm_mode); + } + return temp; +} + +static void +mach_accel_outb(uint16_t port, uint8_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + mach_accel_out(port, val, mach, 1); +} + +static void +mach_accel_outw(uint16_t port, uint16_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + mach_accel_out(port, val, mach, 2); +} + +static uint8_t +mach_accel_inb(uint16_t port, void *p) +{ + mach_t *mach = (mach_t *) p; + return mach_accel_in(port, mach, 1); +} + +static uint16_t +mach_accel_inw(uint16_t port, void *p) +{ + mach_t *mach = (mach_t *) p; + return mach_accel_in(port, mach, 2); +} + +static void +mach32_ap_writeb(uint32_t addr, uint8_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); + mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); + } else { + mach_log("Port WORDB Write=%04x.\n", 0x02e8 + (port_dword << 8)); + mach_accel_outb(0x02e8 + (addr & 1) + (port_dword << 8), val, mach); + } + } else { + mach_log("Linear WORDB Write=%08x.\n", addr); + svga_write_linear(addr, val, &mach->svga); + } +} + +static void +mach32_ap_writew(uint32_t addr, uint16_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); + mach_accel_outw(0x02ee + (port_dword << 8), val, mach); + } else { + mach_log("Port WORDW Write=%04x.\n", 0x02e8 + (port_dword << 8)); + mach_accel_outw(0x02e8 + (port_dword << 8), val, mach); + } + } else { + mach_log("Linear WORDW Write=%08x.\n", addr); + svga_writew_linear(addr, val, &mach->svga); + } +} + +static void +mach32_ap_writel(uint32_t addr, uint32_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + mach_log("Port WORDL Write=%04x.\n", 0x02ee + (port_dword << 8)); + mach_accel_outw(0x02ee + (port_dword << 8), val & 0xffff, mach); + mach_accel_outw(0x02ee + (port_dword << 8) + 4, val >> 16, mach); + } else { + mach_log("Port WORDL Write=%04x.\n", 0x02e8 + (port_dword << 8)); + mach_accel_outw(0x02e8 + (port_dword << 8), val & 0xffff, mach); + mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); + } + } else { + mach_log("Linear WORDL Write=%08x, val=%08x, mode=%d, rop=%02x.\n", addr, val, mach->svga.writemode, mach->svga.gdcreg[3] & 0x18); + svga_writel_linear(addr, val, &mach->svga); + } +} + +static uint8_t +mach32_ap_readb(uint32_t addr, void *p) +{ + mach_t *mach = (mach_t *) p; + uint8_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); + } else { + temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); + } + } else + temp = svga_read_linear(addr, &mach->svga); + + return temp; +} + +static uint16_t +mach32_ap_readw(uint32_t addr, void *p) +{ + mach_t *mach = (mach_t *) p; + uint16_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); + } else { + temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); + } + } else + temp = svga_readw_linear(addr, &mach->svga); + + return temp; +} + +static uint32_t +mach32_ap_readl(uint32_t addr, void *p) +{ + mach_t *mach = (mach_t *) p; + uint32_t temp; + uint8_t port_dword = addr & 0xfc; + + if (((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if (addr & 0x100) { + temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); + temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); + } else { + temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); + temp |= (mach_accel_inw(0x02e8 + (port_dword << 8) + 4, mach) << 8); + } + } else + temp = svga_readl_linear(addr, &mach->svga); + + return temp; +} + +static void +mach32_updatemapping(mach_t *mach) +{ + svga_t *svga = &mach->svga; + + if ((mach->pci_bus && (!(mach->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)))) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mach->mmio_linear_mapping); + return; + } + + if (mach->regs[0xbd] & 4) { + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + mach_log("Bit 2 of BD.\n"); + } else { + switch (svga->gdcreg[6] & 0x0c) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } + + mach_log("Linear base = %08x, aperture = %04x, localcntl = %02x svgagdc = %x.\n", mach->linear_base, mach->memory_aperture, mach->local_cntl, svga->gdcreg[6] & 0x0c); + if (mach->linear_base) { + if (((mach->memory_aperture & 3) == 1) && !mach->pci_bus) { + /*1 MB aperture*/ + mach->ap_size = 1; + mem_mapping_set_addr(&mach->mmio_linear_mapping, mach->linear_base, mach->ap_size << 20); + } else { + /*4 MB aperture*/ + mach->ap_size = 4; + mem_mapping_set_addr(&mach->mmio_linear_mapping, mach->linear_base, mach->ap_size << 20); + } + /*Force IBM/ATI mode on when the MMIO registers are loaded.*/ + if (mach->local_cntl & 0x20) { + if (!ibm8514_on) { + ibm8514_on ^= 1; + svga->adv_flags |= FLAG_ATI; + svga_recalctimings(svga); + } + } + } else { + mach->ap_size = 4; + mem_mapping_disable(&mach->mmio_linear_mapping); + } +} + +static void +mach32_hwcursor_draw(svga_t *svga, int displine) +{ + mach_t *mach = (mach_t *) svga->p; + uint16_t dat; + int comb; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + uint32_t color0, color1; + + if (svga->bpp == 8) { + color0 = svga->pallook[mach->cursor_col_0]; + color1 = svga->pallook[mach->cursor_col_1]; + mach_log("8BPP: Offset = %x, XOFF = %02x, YOFF = %02x.\n", offset, svga->hwcursor_latch.xoff, svga->hwcursor_latch.yoff); + } else if (svga->bpp == 15) { + color0 = video_15to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; + color1 = video_15to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; + mach_log("15BPP: Offset = %x, XOFF = %02x, YOFF = %02x.\n", offset, svga->hwcursor_latch.xoff, svga->hwcursor_latch.yoff); + } else if (svga->bpp == 16) { + color0 = video_16to32[((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0) & 0xffff]; + color1 = video_16to32[((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1) & 0xffff]; + mach_log("16BPP: Offset = %x, XOFF = %02x, YOFF = %02x.\n", offset, svga->hwcursor_latch.xoff, svga->hwcursor_latch.yoff); + } else { + color0 = ((mach->ext_cur_col_0_r << 16) | (mach->ext_cur_col_0_g << 8) | mach->cursor_col_0); + color1 = ((mach->ext_cur_col_1_r << 16) | (mach->ext_cur_col_1_g << 8) | mach->cursor_col_1); + mach_log("24BPP: Offset = %x, XOFF = %02x, YOFF = %02x.\n", offset, svga->hwcursor_latch.xoff, svga->hwcursor_latch.yoff); + } + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + for (int x = 0; x < 64; x += 8) { + dat = svga->vram[svga->hwcursor_latch.addr & svga->vram_mask] | (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 8); + for (int xx = 0; xx < 8; xx++) { + comb = (dat >> (xx << 1)) & 0x03; + if (offset >= svga->hwcursor_latch.x) { + switch (comb) { + case 0: + ((uint32_t *) svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color0; + break; + case 1: + ((uint32_t *) svga->monitor->target_buffer->line[displine])[offset + svga->x_add] = color1; + break; + case 3: + ((uint32_t *) svga->monitor->target_buffer->line[displine])[offset + svga->x_add] ^= 0xffffff; + break; + } + } + offset++; + } + svga->hwcursor_latch.addr += 2; + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + +static void +mach_io_remove(mach_t *mach) +{ + io_removehandler(0x01ce, 2, + mach_in, NULL, NULL, + mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, + mach_in, NULL, NULL, + mach_out, NULL, NULL, mach); + + io_removehandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x2ea, 0x0004, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + + io_removehandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + + io_removehandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_removehandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); +} + +static void +mach_io_set(mach_t *mach) +{ + io_sethandler(0x01ce, 2, + mach_in, NULL, NULL, + mach_out, NULL, NULL, mach); + io_sethandler(0x03c0, 32, + mach_in, NULL, NULL, + mach_out, NULL, NULL, mach); + + io_sethandler(0x2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x2ea, 0x0004, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_sethandler(0x6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x12e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x16e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x1ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x1ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x22e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x5ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x5ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x82e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x86e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x8ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x8ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x92e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x96e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x9ae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x9ee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xa2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xa6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xaae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xaee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xb2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xb6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xbae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xbee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xe2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + + io_sethandler(0xc2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xc6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xcae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xcee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xd2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xd6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xdae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xdee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xe6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xeae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xeee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xf2e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xf6e8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xfae8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xfee8, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + + io_sethandler(0x06ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x0aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x0eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x12ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x16ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x1aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x1eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x26ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x2aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x2eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x32ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x36ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x3aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x3eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x42ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x46ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x4aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x52ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x56ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x5aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x5eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x62ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x66ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x6aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x6eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x72ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x76ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x7aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0x9aee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xa2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xa6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xaaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xaeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xb2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xb6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xbaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xbeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xc2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xc6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xcaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xceee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xd2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xd6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xdaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); + io_sethandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, NULL, mach_accel_outb, mach_accel_outw, NULL, mach); +} + +static uint8_t +mach32_pci_read(int func, int addr, void *p) +{ + mach_t *mach = (mach_t *) p; + uint8_t ret = 0x00; + + switch (addr) { + case 0x00: + ret = 0x02; /*ATI*/ + break; + case 0x01: + ret = 0x10; + break; + + case 0x02: + ret = 0x58; + break; + case 0x03: + ret = 0x41; + break; + + case PCI_REG_COMMAND: + ret = mach->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ + break; + + case 0x07: + ret = 0x01; /*Medium DEVSEL timing*/ + break; + + case 0x0a: + ret = 0x00; /*Supports VGA interface*/ + break; + case 0x0b: + ret = 0x03; + break; + + case 0x10: + ret = 0x00; /*Linear frame buffer address*/ + break; + case 0x11: + ret = 0x00; + break; + case 0x12: + ret = mach->linear_base >> 16; + break; + case 0x13: + ret = mach->linear_base >> 24; + break; + + case 0x30: + ret = (mach->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ + break; + case 0x31: + ret = 0x00; + break; + case 0x32: + ret = mach->pci_regs[0x32]; + break; + case 0x33: + ret = mach->pci_regs[0x33]; + break; + + case 0x3c: + ret = mach->int_line; + break; + case 0x3d: + ret = PCI_INTA; + break; + } + + return ret; +} + +static void +mach32_pci_write(int func, int addr, uint8_t val, void *p) +{ + mach_t *mach = (mach_t *) p; + + switch (addr) { + case PCI_REG_COMMAND: + mach->pci_regs[PCI_REG_COMMAND] = val & 0x27; + mach_io_remove(mach); + if (val & PCI_COMMAND_IO) { + mach_io_set(mach); + } + mach32_updatemapping(mach); + break; + + case 0x12: + mach->linear_base = (mach->linear_base & 0xff000000) | ((val & 0xc0) << 16); + mach32_updatemapping(mach); + break; + case 0x13: + mach->linear_base = (mach->linear_base & 0xc00000) | (val << 24); + mach32_updatemapping(mach); + break; + + case 0x30: + case 0x32: + case 0x33: + mach->pci_regs[addr] = val; + if (mach->pci_regs[0x30] & 0x01) { + uint32_t bios_addr = (mach->pci_regs[0x32] << 16) | (mach->pci_regs[0x33] << 24); + mach_log("Mach32 bios_rom enabled at %08x\n", bios_addr); + mem_mapping_set_addr(&mach->bios_rom.mapping, bios_addr, 0x8000); + } else { + mach_log("Mach32 bios_rom disabled\n"); + mem_mapping_disable(&mach->bios_rom.mapping); + } + return; + + case 0x3c: + mach->int_line = val; + break; + } +} + +static void * +mach8_init(const device_t *info) +{ + mach_t *mach; + svga_t *svga; + ibm8514_t *dev; + uint32_t memory; + + mach = malloc(sizeof(mach_t)); + memset(mach, 0x00, sizeof(mach_t)); + + svga = &mach->svga; + dev = &svga->dev8514; + + mach->pci_bus = !!(info->flags & DEVICE_PCI); + mach->vlb_bus = !!(info->flags & DEVICE_VLB); + dev->local = info->local; + dev->vram_size = (1024 << 10); + dev->vram = calloc(dev->vram_size, 1); + dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->vram_mask = dev->vram_size - 1; + dev->map8 = svga->pallook; + memory = device_get_config_int("memory"); + + if (dev->local) { + if (mach->vlb_bus) + rom_init(&mach->bios_rom, + BIOS_MACH32_VLB_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + else if (mach->pci_bus) + rom_init(&mach->bios_rom, + BIOS_MACH32_PCI_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + else + rom_init(&mach->bios_rom, + BIOS_MACH32_ISA_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + } else { + rom_init(&mach->bios_rom, + BIOS_MACH8_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + } + + svga_init(info, svga, mach, dev->local ? (memory << 10) : (512 << 10), /*default: 512kB for Mach8, 2MB for Mach32*/ + mach_recalctimings, + mach_in, mach_out, + dev->local ? mach32_hwcursor_draw : NULL, + NULL); + + if (dev->local) { + switch (memory) { + case 1024: + mach->misc |= 0x04; + break; + case 2048: + mach->misc |= 0x08; + break; + case 4096: + mach->misc |= 0x0c; + break; + } + svga->hwcursor.cur_ysize = 64; + mach->config1 = 0x20; + mach->config2 = 0x08; + /*Fake the RAMDAC to give the VLB/MCA variants full 24-bit support until said RAMDAC is implemented.*/ + if (mach->vlb_bus) { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_vlb); + mach->config1 |= 0x0c; + mach->config1 |= 0x0400; + } else if (mach->pci_bus) { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_pci); + mach->config1 |= 0x0e; + mach->config1 |= 0x0a00; + mach->config2 |= 0x2000; + svga->ramdac = device_add(&ati68860_ramdac_device); + } else { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); + } + mem_mapping_add(&mach->mmio_linear_mapping, 0, 0, mach32_ap_readb, mach32_ap_readw, mach32_ap_readl, mach32_ap_writeb, mach32_ap_writew, mach32_ap_writel, NULL, MEM_MAPPING_EXTERNAL, mach); + mem_mapping_disable(&mach->mmio_linear_mapping); + } else { + video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); + mach->config1 = 0x02 | 0x20 | 0x80; + mach->config2 = 0x02; + dev->ext_pitch = 1024; + } + + svga->force_old_addr = 1; + svga->miscout = 1; + svga->bpp = 8; + svga->packed_chain4 = 1; + ibm8514_enabled = 1; + ibm8514_has_vga = 1; + dev->ibm_mode = 1; + dev->rowoffset = 128; + mach_io_set(mach); + + if (dev->local) { + svga->decode_mask = (4 << 20) - 1; + mach->cursor_col_1 = 0xff; + mach->ext_cur_col_1_r = 0xff; + mach->ext_cur_col_1_g = 0xff; + dev->ext_crt_pitch = 128; + if (mach->vlb_bus) + ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); + else if (mach->pci_bus) { + ati_eeprom_load(&mach->eeprom, "mach32_pci.nvr", 1); + mem_mapping_disable(&mach->bios_rom.mapping); + mach->card = pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach); + mach->pci_regs[PCI_REG_COMMAND] = 0x83; + mach->pci_regs[0x30] = 0x00; + mach->pci_regs[0x32] = 0x0c; + mach->pci_regs[0x33] = 0x00; + } else + ati_eeprom_load(&mach->eeprom, "mach32.nvr", 1); + } else { + ati_eeprom_load_mach8(&mach->eeprom, "mach8.nvr"); + } + + return (mach); +} + +static int +mach8_available(void) +{ + return rom_present(BIOS_MACH8_ROM_PATH); +} + +static int +mach32_isa_available(void) +{ + return rom_present(BIOS_MACH32_ISA_ROM_PATH); +} + +static int +mach32_vlb_available(void) +{ + return rom_present(BIOS_MACH32_VLB_ROM_PATH); +} + +static int +mach32_pci_available(void) +{ + return rom_present(BIOS_MACH32_PCI_ROM_PATH); +} + +static void +mach_close(void *p) +{ + mach_t *mach = (mach_t *) p; + svga_t *svga = &mach->svga; + ibm8514_t *dev = &svga->dev8514; + + if (dev) { + free(dev->vram); + free(dev->changedvram); + } + + svga_close(svga); + free(mach); +} + +static void +mach_speed_changed(void *p) +{ + mach_t *mach = (mach_t *) p; + svga_t *svga = &mach->svga; + + svga_recalctimings(svga); +} + +static void +mach_force_redraw(void *p) +{ + mach_t *mach = (mach_t *) p; + svga_t *svga = &mach->svga; + + svga->fullchange = changeframecount; +} + +// clang-format off +static const device_config_t mach32_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 2048, + .selection = { + { + .description = "512 KB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "2 MB", + .value = 2048 + }, + { + .description = "4 MB", + .value = 4096 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; + +const device_t mach8_isa_device = { + .name = "ATI Mach8 (ISA)", + .internal_name = "mach8_isa", + .flags = DEVICE_ISA, + .local = 0, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach8_available }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = NULL +}; + +const device_t mach32_isa_device = { + .name = "ATI Mach32 (ISA)", + .internal_name = "mach32_isa", + .flags = DEVICE_ISA, + .local = 1, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach32_isa_available }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = mach32_config +}; + +const device_t mach32_vlb_device = { + .name = "ATI Mach32 (VLB)", + .internal_name = "mach32_vlb", + .flags = DEVICE_VLB, + .local = 1, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach32_vlb_available }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = mach32_config +}; + +const device_t mach32_pci_device = { + .name = "ATI Mach32 (PCI)", + .internal_name = "mach32_pci", + .flags = DEVICE_PCI, + .local = 1, + .init = mach8_init, + .close = mach_close, + .reset = NULL, + { .available = mach32_pci_available }, + .speed_changed = mach_speed_changed, + .force_redraw = mach_force_redraw, + .config = mach32_config +}; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index e9ea4d111..ee5a2117b 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -277,7 +277,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.ena = !!(et4000->regs[0xF7] & 0x80); svga->hwcursor.xoff = et4000->regs[0xE2]; svga->hwcursor.yoff = et4000->regs[0xE6]; - svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((et4000->regs[0xEF] & 4) || ((et4000->type == ET4000W32) && et4000->regs[0xe2] && et4000->regs[0xe6])) ? 128 : 64; + svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = ((et4000->regs[0xEF] & 4) || ((et4000->type == ET4000W32) && (et4000->regs[0xe2] >= 0x1f) && (et4000->regs[0xe6] >= 0x1f))) ? 128 : 64; if (et4000->type == ET4000W32) { if ((svga->bpp == 15) || (svga->bpp == 16)) { @@ -2084,7 +2084,7 @@ et4000w32_blit(int count, int cpu_input, uint32_t src_dat, uint32_t mix_dat, et4 uint8_t source; uint8_t dest; uint8_t rop; - uint8_t out; + uint8_t out = 0; int mixmap; if (!(et4000->acl.status & ACL_XYST) && !et4000->acl.mmu_start) { diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 453972402..7f840d134 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -498,7 +498,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; #define READ_PIXTRANS_WORD \ - if (s3->bpp == 0 && !s3->color_16bit) { \ + if ((s3->bpp == 0) && !s3->color_16bit) { \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ } else { \ @@ -506,7 +506,7 @@ static void s3_visionx68_video_engine_op(uint32_t cpu_dat, s3_t *s3); } #define READ_PIXTRANS_LONG \ - if (s3->bpp == 0 && !s3->color_16bit) { \ + if ((s3->bpp == 0) && !s3->color_16bit) { \ temp = svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx)) & s3->vram_mask]; \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 1)) & s3->vram_mask] << 8); \ temp |= (svga->vram[dword_remap(svga, (s3->accel.dest + s3->accel.cx + 2)) & s3->vram_mask] << 16); \ @@ -2671,6 +2671,7 @@ s3_out(uint16_t addr, uint8_t val, void *p) return; if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) return; + old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; @@ -3075,7 +3076,7 @@ s3_recalctimings(svga_t *svga) svga->rowoffset |= 0x100; } if (!svga->rowoffset) - svga->rowoffset = 256; + svga->rowoffset = 0x100; if ((s3->chip == S3_VISION964) || (s3->chip == S3_86C928)) { if (s3->card_type == S3_ELSAWIN2KPROX_964) @@ -3120,7 +3121,7 @@ s3_recalctimings(svga_t *svga) } } else { if (s3->card_type == S3_NUMBER9_9FX_531) { - if (svga->hdisp == 1600 && s3->width == 1600) + if ((svga->hdisp == 1600) && (s3->width == 1600)) s3->width = 800; } } @@ -3131,10 +3132,10 @@ s3_recalctimings(svga_t *svga) } } - if ((svga->crtc[0x43] & 0x08) && (s3->color_16bit == 0) && (s3->chip <= S3_86C805)) { + if ((svga->crtc[0x43] & 0x08) && !s3->color_16bit && (s3->chip <= S3_86C805)) { s3->color_16bit = 1; - s3->width = 1024; - } else if (!(svga->crtc[0x43] & 0x08) && (s3->color_16bit == 1) && (s3->chip <= S3_86C805)) { + s3->width = 1024; + } else if (!(svga->crtc[0x43] & 0x08) && s3->color_16bit && (s3->chip <= S3_86C805)) { s3->color_16bit = 0; if (s3->chip <= S3_86C924) { if (s3->accel.advfunc_cntl & 4) @@ -4808,9 +4809,9 @@ polygon_setup(s3_t *s3) } #define READ(addr, dat) \ - if (s3->bpp == 0 && !s3->color_16bit) \ + if ((s3->bpp == 0) && !s3->color_16bit) \ dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \ - else if (s3->bpp == 1 || s3->color_16bit) \ + else if ((s3->bpp == 1) || s3->color_16bit) \ 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]; \ @@ -5660,10 +5661,10 @@ polygon_setup(s3_t *s3) } #define WRITE(addr, dat) \ - if (s3->bpp == 0 && !s3->color_16bit) { \ + if ((s3->bpp == 0) && !s3->color_16bit) { \ svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \ svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = svga->monitor->mon_changeframecount; \ - } else if (s3->bpp == 1 || s3->color_16bit) { \ + } else if ((s3->bpp == 1) || s3->color_16bit) { \ vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \ svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else if (s3->bpp == 2) { \ @@ -6123,7 +6124,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dat_count = 0; if (cpu_input && (((s3->accel.multifunc[0xa] & 0xc0) != 0x80) || (!(s3->accel.cmd & 2)))) { - if ((s3->bpp == 3) && count == 2) { + if ((s3->bpp == 3) && (count == 2)) { if (s3->accel.dat_count) { cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; count = 4; @@ -6133,20 +6134,20 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dat_count = 1; } } - if (s3->bpp == 1 || s3->color_16bit) + if ((s3->bpp == 1) || s3->color_16bit) count >>= 1; if (s3->bpp == 3) count >>= 2; } - if (s3->bpp == 0 && !s3->color_16bit) + if ((s3->bpp == 0) && !s3->color_16bit) rd_mask &= 0xff; - else if (s3->bpp == 1 || s3->color_16bit) + else if ((s3->bpp == 1) || s3->color_16bit) rd_mask &= 0xffff; - if (s3->bpp == 0 && !s3->color_16bit) + if ((s3->bpp == 0) && !s3->color_16bit) compare &= 0xff; - if (s3->bpp == 1 || s3->color_16bit) + if ((s3->bpp == 1) || s3->color_16bit) compare &= 0xffff; switch (s3->accel.cmd & 0x600) { @@ -6212,6 +6213,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ cpu_dat >>= 8; else cpu_dat >>= 16; + if (!s3->accel.ssv_len) break; @@ -6259,18 +6261,16 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = s3->accel.cur_x & 0x7ff; s3->accel.cy = s3->accel.cur_y & 0x7ff; - if (s3->accel.cur_x & 0x800) { + if (s3->accel.cur_x & 0x800) s3->accel.cx |= ~0x7ff; - } - if (s3->accel.cur_y & 0x800) { + + if (s3->accel.cur_y & 0x800) s3->accel.cy |= ~0x7ff; - } s3->accel.sy = s3->accel.maj_axis_pcnt; - if (s3_cpu_src(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; @@ -6305,11 +6305,10 @@ 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 && !s3->color_16bit) + if ((s3->bpp == 0) && !s3->color_16bit) cpu_dat >>= 8; - else { + else cpu_dat >>= 16; - } if (!s3->accel.sy) { break; @@ -6351,13 +6350,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cur_y = s3->accel.cy; } else /*Bresenham*/ { - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/ + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; } while (count-- && s3->accel.sy >= 0) { - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && s3->accel.temp_cnt == 0) { + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && !s3->accel.temp_cnt) { mix_dat >>= 16; s3->accel.temp_cnt = 16; } @@ -6567,7 +6566,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ mix_dat |= 1; } - if (s3->bpp == 0 && !s3->color_16bit) + if ((s3->bpp == 0) && !s3->color_16bit) cpu_dat >>= 8; else { cpu_dat >>= 16; @@ -8021,7 +8020,7 @@ s3_init(const device_t *info) switch (vram) { case 0: /* 512 kB */ svga->vram_mask = (1 << 19) - 1; - svga->vram_max = 2 << 20; + svga->vram_max = 1 << 19; break; case 1: /* 1 MB */ /* VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus. @@ -8029,7 +8028,7 @@ s3_init(const device_t *info) This works with the #9 9FX BIOS, and matches how my real Trio64 behaves, but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference? */ svga->vram_mask = (1 << 20) - 1; - svga->vram_max = 2 << 20; + svga->vram_max = 1 << 20; break; case 2: default: /*2 MB */ diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index feaba7fe8..1eb1fa855 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -3372,7 +3372,7 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.base_w = s3d_tri->tws; tex_base = s3d_tri->tex_base; - for (uint8_t c = 9; c >= 0; c--) { + for (int c = 9; c >= 0; c--) { state.texture[c] = (uint16_t *) &virge->svga.vram[tex_base]; if (c <= state.max_d) tex_base += ((1 << (c * 2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index d8829eb2f..913a052ff 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -41,6 +41,7 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> +#include <86box/vid_xga_device.h> void svga_doblit(int wx, int wy, svga_t *svga); @@ -131,7 +132,7 @@ svga_out(uint16_t addr, uint8_t val, void *p) if (svga->attraddr < 16) svga->fullchange = svga->monitor->mon_changeframecount; if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { - for (uint8_t c = 0; c < 16; c++) { + for (int c = 0; c < 16; c++) { if (svga->attrregs[0x10] & 0x80) { svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); } else { @@ -165,6 +166,12 @@ svga_out(uint16_t addr, uint8_t val, void *p) io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); svga_recalctimings(svga); break; + case 0x3c3: + if (xga_enabled) { + svga->xga.on = (val & 0x01) ? 0 : 1; + vga_on = !svga->xga.on; + } + break; case 0x3c4: svga->seqaddr = val; break; @@ -407,7 +414,7 @@ svga_set_ramdac_type(svga_t *svga, int type) if (svga->ramdac_type != type) { svga->ramdac_type = type; - for (uint16_t c = 0; c < 256; c++) { + for (int c = 0; c < 256; c++) { if (svga->ramdac_type == RAMDAC_8BIT) svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); else @@ -583,8 +590,14 @@ svga_recalctimings(svga_t *svga) svga->recalctimings_ex(svga); } } else { - if (ibm8514_enabled) - ibm8514_recalctimings(svga); + if (ibm8514_enabled) { + if (svga->dev8514.local) { + if (svga->recalctimings_ex) { + svga->recalctimings_ex(svga); + } + } else + ibm8514_recalctimings(svga); + } if (xga_enabled) xga_recalctimings(svga); } @@ -597,8 +610,13 @@ svga_recalctimings(svga_t *svga) crtcconst = svga->clock * svga->char_width; - disptime = svga->htotal; - _dispontime = svga->hdisp_time; + if (ibm8514_on && !svga->dev8514.local) { + disptime = svga->dev8514.h_total; + _dispontime = svga->dev8514.h_disp; + } else { + disptime = svga->htotal; + _dispontime = svga->hdisp_time; + } if (svga->seqregs[1] & 8) { disptime *= 2; @@ -678,16 +696,20 @@ void svga_poll(void *p) { svga_t *svga = (svga_t *) p; + ibm8514_t *dev = &svga->dev8514; uint32_t x; uint32_t blink_delay; int wx; int wy; int ret; int old_ma; + int linecountff = 0; if (!vga_on && ibm8514_enabled && ibm8514_on) { - ibm8514_poll(&svga->dev8514, svga); - return; + if (!dev->local) { + ibm8514_poll(dev, svga); + return; + } } else if (!vga_on && xga_enabled && svga->xga.on) { xga_poll(&svga->xga, svga); return; @@ -695,22 +717,22 @@ svga_poll(void *p) if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { - svga->hwcursor_on = svga->hwcursor.cur_ysize - svga->hwcursor_latch.yoff; + svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - svga->hwcursor_latch.yoff; svga->hwcursor_oddeven = 0; } if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && svga->interlace) { - svga->hwcursor_on = svga->hwcursor.cur_ysize - (svga->hwcursor_latch.yoff + 1); + svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - (svga->hwcursor_latch.yoff + 1); svga->hwcursor_oddeven = 1; } if (svga->displine == svga->dac_hwcursor_latch.y && svga->dac_hwcursor_latch.ena) { - svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - svga->dac_hwcursor_latch.yoff; + svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - svga->dac_hwcursor_latch.yoff; svga->dac_hwcursor_oddeven = 0; } if (svga->displine == (svga->dac_hwcursor_latch.y + 1) && svga->dac_hwcursor_latch.ena && svga->interlace) { - svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1); + svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1); svga->dac_hwcursor_oddeven = 1; } @@ -783,8 +805,14 @@ svga_poll(void *p) if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount)) svga->con = 0; if (svga->dispon) { - if (svga->linedbl && !svga->linecountff) { - svga->linecountff = 1; + /*Real IBM 8514/A or compatibility mode doesn't have linedbl, so skip those.*/ + if (dev->local && ibm8514_on) { + svga->linedbl = 0; + svga->linecountff = 0; + linecountff = 1; + } + if (svga->linedbl && !svga->linecountff && !linecountff) { + svga->linecountff = 1; svga->ma = svga->maback; } else if (svga->sc == svga->rowcount) { svga->linecountff = 0; @@ -793,23 +821,24 @@ svga_poll(void *p) svga->maback += (svga->rowoffset << 3); if (svga->interlace) svga->maback += (svga->rowoffset << 3); + svga->maback &= svga->vram_display_mask; svga->ma = svga->maback; } else { svga->linecountff = 0; svga->sc++; - svga->sc &= 31; + svga->sc &= 0x1f; svga->ma = svga->maback; } } - svga->hsync_divisor = !svga->hsync_divisor; + svga->hsync_divisor ^= 1; if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) return; svga->vc++; - svga->vc &= 2047; + svga->vc &= 0x7ff; if (svga->vc == svga->split) { ret = 1; @@ -835,6 +864,7 @@ svga_poll(void *p) if (svga->vc == svga->dispend) { if (svga->vblank_start) svga->vblank_start(svga); + svga->dispon = 0; blink_delay = (svga->crtc[11] & 0x60) >> 5; if (svga->crtc[10] & 0x20) @@ -846,6 +876,7 @@ svga_poll(void *p) if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) svga->fullchange = 2; + svga->blink = (svga->blink + 1) & 0x7f; for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { @@ -888,12 +919,18 @@ svga_poll(void *p) svga->monitor->mon_changeframecount = svga->interlace ? 3 : 2; svga->vslines = 0; - if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); - else - svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + if ((dev->local && vga_on) || !dev->local) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); + else + svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5); + } else if (dev->local && ibm8514_on) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); + else + svga->ma = svga->maback = svga->ma_latch; + } svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj; - svga->ma = (svga->ma << 2); svga->maback = (svga->maback << 2); svga->ca = (svga->ca << 2); @@ -958,9 +995,9 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->monitor_index = monitor_index_global; svga->monitor = &monitors[svga->monitor_index]; - for (uint16_t c = 0; c < 256; c++) { + for (int c = 0; c < 256; c++) { e = c; - for (uint8_t d = 0; d < 8; d++) { + for (int d = 0; d < 8; d++) { svga_rotate[d][c] = e; e = (e >> 1) | ((e & 1) ? 0x80 : 0); } @@ -1100,7 +1137,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) if (!linear) { if (xga_enabled) { - if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl == 1)) { + if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl >= 1)) { if (val == 0xa5) { /*Memory size test of XGA*/ svga->xga.test = val; svga->xga.a5_test = 1; @@ -1108,7 +1145,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) } else if (val == 0x5a) { svga->xga.test = val; return; - } else if (val == 0x12 || val == 0x34) { + } else if ((val == 0x12) || (val == 0x34)) { addr += svga->xga.write_bank; svga->xga.vram[addr & svga->xga.vram_mask] = val; svga->xga.linear_endian_reverse = 1; @@ -1145,10 +1182,18 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) if (addr & 1) writemask2 <<= 1; addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - + if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) { + addr &= svga->vram_mask; + } else + addr <<= 2; + } else { + if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + addr &= svga->vram_mask; + } else + addr <<= 2; + } addr &= svga->decode_mask; if (svga->translate_address) @@ -1303,7 +1348,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) if (!linear) { if (xga_enabled) { - if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl == 1)) { + if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl >= 1)) { if (svga->xga.test == 0xa5) { /*Memory size test of XGA*/ svga->xga.on = 1; vga_on = !svga->xga.on; @@ -1312,7 +1357,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) svga->xga.on = 1; vga_on = !svga->xga.on; return svga->xga.test; - } else if (addr == 0xa0000 || addr == 0xa0010) { + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { addr += svga->xga.read_bank; return svga->xga.vram[addr & svga->xga.vram_mask]; } @@ -1354,11 +1399,24 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - + if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) + addr &= svga->vram_mask; + else + addr <<= 2; + } else { + if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) { + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + latch_addr = (addr & svga->vram_mask) & ~3; + for (uint8_t i = 0; i < count; i++) + svga->latch.b[i] = svga->vram[latch_addr | i]; + return svga->vram[addr & svga->vram_mask]; + } else + addr <<= 2; + } addr &= svga->decode_mask; + if (svga->translate_address) { latch_addr = svga->translate_address(latch_addr, p); addr = svga->translate_address(addr, p); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index a2cead1ec..aaf407ca4 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -36,6 +36,7 @@ #include <86box/vid_ega.h> #include <86box/vid_colorplus.h> #include <86box/vid_mda.h> +#include <86box/vid_xga_device.h> typedef struct { const device_t *device; @@ -79,6 +80,8 @@ video_cards[] = { { &vid_none_device }, { &vid_internal_device }, { &atiega_device }, + { &mach8_isa_device, VIDEO_FLAG_TYPE_8514 }, + { &mach32_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach64gx_isa_device }, { &ati28800k_device }, { &ati18800_vga88_device }, @@ -112,6 +115,7 @@ video_cards[] = { { &hercules_device, VIDEO_FLAG_TYPE_MDA }, { &herculesplus_device, VIDEO_FLAG_TYPE_MDA }, { &incolor_device }, + { &inmos_isa_device, VIDEO_FLAG_TYPE_XGA }, { &im1024_device }, { &iskra_ega_device }, { &et4000_kasan_isa_device }, @@ -154,6 +158,7 @@ video_cards[] = { { &gd5428_mca_device }, { &et4000_mca_device }, { &radius_svga_multiview_mca_device }, + { &mach32_pci_device, VIDEO_FLAG_TYPE_8514 }, { &mach64gx_pci_device }, { &mach64vt2_device }, { &et4000w32p_videomagic_revb_pci_device }, @@ -211,6 +216,7 @@ video_cards[] = { { &voodoo_3_1000_device }, { &voodoo_3_2000_device }, { &voodoo_3_3000_device }, + { &mach32_vlb_device, VIDEO_FLAG_TYPE_8514 }, { &mach64gx_vlb_device }, { &et4000w32i_vlb_device }, { &et4000w32p_videomagic_revb_vlb_device }, @@ -431,3 +437,15 @@ video_is_ega_vga(void) { return (video_get_type() == VIDEO_FLAG_TYPE_SPECIAL); } + +int +video_is_8514(void) +{ + return (video_get_type() == VIDEO_FLAG_TYPE_8514); +} + +int +video_is_xga(void) +{ + return (video_get_type() == VIDEO_FLAG_TYPE_XGA); +} diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 0c795d132..db1ae0afb 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -37,6 +37,7 @@ #define XGA_BIOS_PATH "roms/video/xga/XGA_37F9576_Ver200.BIN" #define XGA2_BIOS_PATH "roms/video/xga/xga2_v300.bin" +#define INMOS_XGA_BIOS_PATH "roms/video/xga/InMOS XGA - Fairchild NM27C256Q-150.BIN" static video_timings_t timing_xga_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; @@ -44,16 +45,86 @@ static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .writ static void xga_ext_outb(uint16_t addr, uint8_t val, void *p); static uint8_t xga_ext_inb(uint16_t addr, void *p); +int xga_has_vga = 0; + +void +svga_xga_out(uint16_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + uint8_t old; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (svga->crtcreg & 0x20) + return; + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + if (old != val) { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { + svga->fullchange = 3; + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + } else { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + } + break; + } + svga_out(addr, val, svga); +} + +uint8_t +svga_xga_in(uint16_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + uint8_t temp; + + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + if (svga->crtcreg & 0x20) + temp = 0xff; + else + temp = svga->crtc[svga->crtcreg]; + break; + default: + temp = svga_in(addr, svga); + break; + } + return temp; +} + void xga_updatemapping(svga_t *svga) { xga_t *xga = &svga->xga; - //pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x, map = %x.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode, svga->gdcreg[6] & 0x0c); + //pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, access mode = %x, map = %x, endian reverse = %d, a5test = %d, XGA on = %d.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->access_mode, svga->gdcreg[6] & 0x0c, xga->linear_endian_reverse, xga->a5_test, xga->on); if (((xga->op_mode & 7) >= 4) || ((xga->op_mode & 7) == 0)) { - if (xga->aperture_cntl == 1) { + if ((xga->aperture_cntl == 1) || (xga->aperture_cntl == 2)) { mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); + if (xga->aperture_cntl == 1) + mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); + else + mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); + mem_mapping_enable(&xga->video_mapping); xga->banked_mask = 0xffff; if (!xga->linear_endian_reverse) @@ -63,38 +134,23 @@ xga_updatemapping(svga_t *svga) mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); mem_mapping_enable(&xga->video_mapping); xga->banked_mask = 0xffff; - if (xga->pos_regs[4] & 1) - mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); - else if (xga->base_addr_1mb) + if (xga->base_addr_1mb) mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); else mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); if (((xga->op_mode & 7) == 4) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && xga->on) xga->linear_endian_reverse = 1; - else if (((xga->op_mode & 7) == 0) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && !xga->on) + else if (((xga->op_mode & 7) == 0) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && !xga->on) { xga->linear_endian_reverse = 1; - xga->on = 0; - vga_on = !xga->on; - } else { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); - mem_mapping_enable(&xga->video_mapping); - xga->banked_mask = 0xffff; - mem_mapping_disable(&xga->linear_mapping); + } + if (xga->a5_test && (xga->access_mode & 8) && !xga->linear_endian_reverse) { + xga->on = 0; + vga_on = !xga->on; + } } - } else { - xga->on = 0; - vga_on = !xga->on; - mem_mapping_disable(&svga->mapping); - if (xga->aperture_cntl == 2) - mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); - mem_mapping_enable(&xga->video_mapping); - xga->banked_mask = 0xffff; - mem_mapping_disable(&xga->linear_mapping); - //pclog("XGA opmode (not extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, xga->disp_cntl_2 & 7, xga->aperture_cntl); + //pclog("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, xga->disp_cntl_2 & 7, xga->aperture_cntl); } + //pclog("VGA on = %d.\n", vga_on); } void @@ -126,19 +182,19 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; - switch (xga->clk_sel_1 & 0x0c) { + switch ((xga->clk_sel_1 >> 2) & 3) { case 0: if (xga->clk_sel_2 & 0x80) { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 41539000.0; + svga->clock = (cpuclock * (double) (1ull << 32)) / 41539000.0; } else { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + svga->clock = (cpuclock * (double) (1ull << 32)) / 25175000.0; } break; - case 4: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 28322000.0; + case 1: + svga->clock = (cpuclock * (double) (1ull << 32)) / 28322000.0; break; - case 0x0c: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + case 3: + svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; break; } } @@ -309,7 +365,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) if ((xga->sprite_pos >= 0) && (xga->sprite_pos <= 16)) { if ((xga->op_mode & 7) >= 5) xga->cursor_data_on = 1; - else if (xga->sprite_pos >= 1) + else if ((xga->sprite_pos >= 1) || ((xga->disp_cntl_2 & 7) > 3)) xga->cursor_data_on = 1; else if (xga->aperture_cntl == 0) { if (xga->linear_endian_reverse && !(xga->access_mode & 8)) @@ -448,7 +504,7 @@ xga_ext_inb(uint16_t addr, void *p) { svga_t *svga = (svga_t *) p; xga_t *xga = &svga->xga; - uint8_t ret; + uint8_t ret = 0xff; uint8_t index; switch (addr & 0x0f) { @@ -474,7 +530,10 @@ xga_ext_inb(uint16_t addr, void *p) case 0x0f: switch (xga->regs_idx) { case 4: - ret = (xga->bus & DEVICE_MCA) ? 1 : 0; + if (xga->bus & DEVICE_MCA) + ret = 0x01; /*32-bit MCA*/ + else + ret = 0x10; /*16-bit ISA*/ break; case 0x10: ret = xga->htotal & 0xff; @@ -653,6 +712,16 @@ xga_ext_inb(uint16_t addr, void *p) ret = xga->clk_sel_2; break; + case 0x74: + if (xga->bus & DEVICE_MCA) + ret = xga->regs[xga->regs_idx]; + else { + ret = (xga->dma_channel << 1); + if (xga->dma_channel) + ret |= 1; + } + break; + default: ret = xga->regs[xga->regs_idx]; break; @@ -678,15 +747,35 @@ xga_ext_inb(uint16_t addr, void *p) dat = xga->vram[(addr + 1) & (xga->vram_mask - 1)] & 0xff; \ dat |= (xga->vram[(addr) & (xga->vram_mask - 1)] << 8); +#define READL(addr, dat) \ + dat = *(uint32_t *) &xga->vram[(addr) & (xga->vram_mask)]; + +#define READL_REVERSE(addr, dat) \ + dat = xga->vram[(addr + 3) & (xga->vram_mask - 3)] & 0xff; \ + dat |= (xga->vram[(addr + 2) & (xga->vram_mask - 3)] << 8); \ + dat |= (xga->vram[(addr + 1) & (xga->vram_mask - 3)] << 16); \ + dat |= (xga->vram[(addr) & (xga->vram_mask - 3)] << 24); + #define WRITEW(addr, dat) \ *(uint16_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \ xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; +#define WRITEL(addr, dat) \ + *(uint32_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \ + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; + #define WRITEW_REVERSE(addr, dat) \ xga->vram[((addr + 1)) & (xga->vram_mask - 1)] = dat & 0xff; \ xga->vram[((addr)) & (xga->vram_mask - 1)] = dat >> 8; \ xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; +#define WRITEL_REVERSE(addr, dat) \ + xga->vram[((addr + 3)) & (xga->vram_mask - 3)] = dat & 0xff; \ + xga->vram[((addr + 2)) & (xga->vram_mask - 3)] = dat >> 8; \ + xga->vram[((addr + 1)) & (xga->vram_mask - 3)] = dat >> 16; \ + xga->vram[((addr)) & (xga->vram_mask - 3)] = dat >> 24; \ + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; + #define ROP(mix, d, s) \ { \ switch ((mix) ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) { \ @@ -859,6 +948,23 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int byte = mem_readw_phys(addr); } return byte; + case 5: /*24-bit*/ + addr += (y * (width << 2)); + addr += (x << 2); + if (!skip) { + if ((xga->accel.px_map_format[map] & 8)) { + if (xga->linear_endian_reverse) { + READL(addr, byte); + } else { + READL_REVERSE(addr, byte); + } + } else { + READL(addr, byte); + } + } else { + byte = mem_readl_phys(addr); + } + return byte; } return 0; @@ -936,6 +1042,22 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui } mem_writew_phys(addr, pixel); break; + case 5: /*24-bit*/ + addr += (y * (width) << 2); + addr += (x << 2); + if (!skip) { + if ((xga->accel.px_map_format[map] & 8)) { + if (xga->linear_endian_reverse) { + WRITEL(addr, pixel); + } else { + WRITEL_REVERSE(addr, pixel); + } + } else { + WRITEL(addr, pixel); + } + } + mem_writel_phys(addr, pixel); + break; } } @@ -1447,6 +1569,10 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) if (addr >= 0x1800) { switch (addr & 0x7f) { + case 0x11: + xga->accel.control = val; + break; + case 0x12: xga->accel.px_map_idx = val & 3; break; @@ -1923,11 +2049,21 @@ xga_mem_read(uint32_t addr, xga_t *xga, svga_t *svga) uint8_t temp = 0; addr &= 0x1fff; - if (addr < 0x1800) { - temp = xga->bios_rom.rom[addr]; + if (!xga_has_vga) + temp = xga->bios_rom.rom[addr]; + else + temp = xga->vga_bios_rom.rom[addr]; } else { switch (addr & 0x7f) { + case 0x11: + temp = xga->accel.control; + if (xga->accel.control & 0x08) + temp |= 0x10; + else + temp &= ~0x10; + break; + case 0x20: temp = xga->accel.bres_err_term & 0xff; break; @@ -2092,8 +2228,9 @@ xga_render_overscan_left(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; + uint32_t *line_ptr = svga->monitor->target_buffer->line[xga->displine + svga->y_add]; for (int i = 0; i < svga->x_add; i++) - buffer32->line[xga->displine + svga->y_add][i] = svga->overscan_color; + *line_ptr++ = svga->overscan_color; } static void @@ -2107,9 +2244,10 @@ xga_render_overscan_right(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; - right = (overscan_x >> 1); + uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp]; + right = (overscan_x >> 1); for (int i = 0; i < right; i++) - buffer32->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp + i] = svga->overscan_color; + *line_ptr++ = svga->overscan_color; } static void @@ -2122,7 +2260,7 @@ xga_render_8bpp(xga_t *xga, svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2159,7 +2297,7 @@ xga_render_16bpp(xga_t *xga, svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; + p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2524,7 +2662,7 @@ xga_poll(xga_t *xga, svga_t *svga) } xga->vc++; - xga->vc &= 2047; + xga->vc &= 0x7ff; if (xga->vc == xga->split) { if (xga->interlace && xga->oddeven) @@ -2683,8 +2821,149 @@ static uint8_t xga_pos_in(uint16_t addr, void *priv) { svga_t *svga = (svga_t *) priv; + xga_t *xga = &svga->xga; + uint8_t ret = 0xff; - return (xga_mca_read(addr, svga)); + if (xga_has_vga) { + switch (addr) { + case 0x0100: + case 0x0101: + if (xga->instance_isa == xga->instance_num) + ret = xga->pos_regs[addr & 7]; + else + ret = 0xff; + break; + case 0x0102: + case 0x0105: + ret = xga->pos_regs[addr & 7]; + break; + case 0x0106: + ret = xga->pos_idx >> 8; + break; + case 0x0107: + ret = xga->pos_idx & 0xff; + break; + case 0x0103: + if (!(xga->pos_idx & 3)) { + ret = xga->pos_regs[3]; + } else + ret = 0; + //pclog("POS IDX for 0103 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); + break; + case 0x0104: + switch (xga->pos_idx & 3) { + case 0: + ret = xga->pos_regs[4]; + break; + case 1: + ret = xga->pos_regs[0]; + break; + case 2: + ret = xga->pos_regs[1]; + break; + case 3: + ret = 0; + break; + } + //pclog("POS IDX for 0104 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); + break; + case 0x0108: + case 0x0109: + case 0x010a: + case 0x010b: + case 0x010c: + case 0x010d: + case 0x010e: + case 0x010f: + xga->instance_num = addr & 7; + if (xga->instance_isa == xga->instance_num) + ret = xga->instance_isa; + else + ret = 0; + + ret |= xga->isa_pos_enable; + break; + } + } else { + switch (addr) { + case 0x0100: + case 0x0101: + ret = xga->pos_regs[addr & 7]; + break; + case 0x0103: + ret = xga->pos_regs[3] | 7; + ret |= (xga->dma_channel << 3); + break; + case 0x0102: + case 0x0104: + case 0x0105: + case 0x0106: + case 0x0107: + ret = (xga_mca_read(addr, svga)); + break; + case 0x0108: + case 0x0109: + case 0x010a: + case 0x010b: + case 0x010c: + case 0x010d: + case 0x010e: + case 0x010f: + xga->instance_num = addr & 7; + if (xga->instance_isa == xga->instance_num) + ret = xga->instance_isa; + else + ret = 0; + + ret |= xga->isa_pos_enable; + break; + } + } + return ret; +} + +static void +xga_pos_out(uint16_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = &svga->xga; + + if (xga_has_vga) { + switch (addr) { + case 0x0106: + xga->pos_idx = (xga->pos_idx & 0x00ff) | (val << 8); + break; + case 0x0107: + xga->pos_idx = (xga->pos_idx & 0xff00) | (val); + //pclog("POS IDX Write = %04x.\n", xga->pos_idx); + break; + case 0x0108: + case 0x0109: + case 0x010a: + case 0x010b: + case 0x010c: + case 0x010d: + case 0x010e: + case 0x010f: + xga->instance_num = addr & 7; + xga->isa_pos_enable = val & 0x08; + break; + } + } else { + switch (addr) { + case 0x0108: + case 0x0109: + case 0x010a: + case 0x010b: + case 0x010c: + case 0x010d: + case 0x010e: + case 0x010f: + xga->instance_num = addr & 7; + xga->isa_pos_enable = val & 0x08; + break; + } + } } static void @@ -2700,7 +2979,10 @@ static void uint32_t temp; uint8_t *rom = NULL; + xga->ext_mem_addr = device_get_config_hex16("ext_mem_addr"); + xga->instance_isa = device_get_config_int("instance"); xga->type = device_get_config_int("type"); + xga->dma_channel = device_get_config_int("dma"); xga->bus = info->flags; xga->vram_size = (1024 << 10); @@ -2739,12 +3021,16 @@ static void xga->rom_addr = 0; rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); } else { - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa); - xga->pos_regs[2] = 1 | 0x0c | 0xf0; + if (xga_has_vga) { + rom_init(&xga->vga_bios_rom, INMOS_XGA_BIOS_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa); + + xga->pos_regs[2] = 1 | (xga->instance_isa << 1) | xga->ext_mem_addr; xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; xga->pos_regs[4] = 1 | 2; xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); - xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); } mem_mapping_add(&xga->video_mapping, 0, 0, xga_readb, xga_readw, xga_readl, @@ -2755,7 +3041,7 @@ static void NULL, MEM_MAPPING_EXTERNAL, svga); mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, xga_memio_writeb, xga_memio_writew, xga_memio_writel, - xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + xga_has_vga ? xga->vga_bios_rom.rom : xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); mem_mapping_disable(&xga->video_mapping); mem_mapping_disable(&xga->linear_mapping); @@ -2768,13 +3054,41 @@ static void mca_add(xga_mca_read, xga_mca_write, xga_mca_feedb, xga_mca_reset, svga); } else { io_sethandler(0x0100, 0x0008, xga_pos_in, NULL, NULL, NULL, NULL, NULL, svga); + if (xga_has_vga) + io_sethandler(0x0106, 0x0002, NULL, NULL, NULL, xga_pos_out, NULL, NULL, svga); + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + io_sethandler(0x0108, 0x0008, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); } - return svga; } +static void + * + svga_xga_init(const device_t *info) +{ + svga_t *svga = malloc(sizeof(svga_t)); + memset(svga, 0, sizeof(svga_t)); + + video_inform(VIDEO_FLAG_TYPE_XGA, &timing_xga_isa); + + svga_init(info, svga, svga, 1 << 18, /*256kB*/ + NULL, + svga_xga_in, svga_xga_out, + NULL, + NULL); + + io_sethandler(0x03c0, 0x0020, svga_xga_in, NULL, NULL, svga_xga_out, NULL, NULL, svga); + + svga->bpp = 8; + svga->miscout = 1; + xga_has_vga = 1; + xga_enabled = 1; + + return xga_init(info); +} + static void xga_close(void *p) { @@ -2793,6 +3107,12 @@ xga_available(void) return rom_present(XGA_BIOS_PATH) && rom_present(XGA2_BIOS_PATH); } +static int +inmos_xga_available(void) +{ + return rom_present(INMOS_XGA_BIOS_PATH); +} + static void xga_speed_changed(void *p) { @@ -2809,7 +3129,7 @@ xga_force_redraw(void *p) svga->fullchange = svga->monitor->mon_changeframecount; } -static const device_config_t xga_configuration[] = { +static const device_config_t xga_mca_configuration[] = { // clang-format off { .name = "type", @@ -2835,6 +3155,91 @@ static const device_config_t xga_configuration[] = { // clang-format on }; +static const device_config_t xga_isa_configuration[] = { + // clang-format off + { + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "XGA-1", + .value = 0 + }, + { + .description = "XGA-2", + .value = 1 + }, + { .description = "" } + } + }, + { + .name = "instance", + .description = "Instance", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 6, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "0 (2100h-210Fh)", .value = 0 }, + { .description = "1 (2110h-211Fh)", .value = 1 }, + { .description = "2 (2120h-212Fh)", .value = 2 }, + { .description = "3 (2130h-213Fh)", .value = 3 }, + { .description = "4 (2140h-214Fh)", .value = 4 }, + { .description = "5 (2150h-215Fh)", .value = 5 }, + { .description = "6 (2160h-216Fh)", .value = 6 }, + { .description = "7 (2170h-217Fh)", .value = 7 }, + { .description = "" } + }, + }, + { + .name = "ext_mem_addr", + .description = "MMIO address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x00f0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800h", .value = 0x0040 }, + { .description = "CA00h", .value = 0x0050 }, + { .description = "CC00h", .value = 0x0060 }, + { .description = "CE00h", .value = 0x0070 }, + { .description = "D000h", .value = 0x0080 }, + { .description = "D200h", .value = 0x0090 }, + { .description = "D400h", .value = 0x00a0 }, + { .description = "D600h", .value = 0x00b0 }, + { .description = "D800h", .value = 0x00c0 }, + { .description = "DA00h", .value = 0x00d0 }, + { .description = "DC00h", .value = 0x00e0 }, + { .description = "DE00h", .value = 0x00f0 }, + { .description = "" } + }, + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + const device_t xga_device = { .name = "XGA (MCA)", .internal_name = "xga_mca", @@ -2846,7 +3251,7 @@ const device_t xga_device = { { .available = xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, - .config = xga_configuration + .config = xga_mca_configuration }; const device_t xga_isa_device = { @@ -2860,13 +3265,27 @@ const device_t xga_isa_device = { { .available = xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, - .config = xga_configuration + .config = xga_isa_configuration +}; + +const device_t inmos_isa_device = { + .name = "INMOS XGA (ISA)", + .internal_name = "inmos_xga_isa", + .flags = DEVICE_ISA | DEVICE_AT, + .local = 0, + .init = svga_xga_init, + .close = xga_close, + .reset = xga_reset, + { .available = inmos_xga_available }, + .speed_changed = xga_speed_changed, + .force_redraw = xga_force_redraw, + .config = xga_isa_configuration }; void xga_device_add(void) { - if (!xga_enabled) + if (!xga_enabled || (xga_has_vga && xga_enabled)) return; if (machine_has_bus(machine, MACHINE_BUS_MCA)) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9c18ae72a..806f2b45b 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -242,7 +242,7 @@ PROG := 86Box # Nothing should need changing from here on.. # ######################################################################### VPATH := $(EXPATH) . $(CODEGEN) minitrace cpu cpu/softfloat \ - cdrom chipset device disk disk/minivhd floppy \ + cpu/808x cdrom chipset device disk disk/minivhd floppy \ game machine mem printer \ sio sound \ sound/munt sound/munt/c_interface sound/munt/sha1 \ @@ -547,11 +547,13 @@ MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma. MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o row.o smram.o spd.o sst_flash.o +CPU808XOBJ := queue.o + CPUOBJ := $(DYNARECOBJ) \ $(CGTOBJ) \ cpu.o cpu_table.o fpu.o x86.o \ 8080.o 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \ - x86seg.o x87.o x87_timings.o \ + x86_ops_mmx.o x86seg.o x87.o x87_timings.o \ f2xm1.o fpatan.o fprem.o fsincos.o fyl2x.o softfloat_poly.o softfloat.o softfloat16.o \ softfloat-muladd.o softfloat-round-pack.o softfloat-specialize.o softfloatx80.o @@ -711,6 +713,7 @@ VIDOBJ := agpgart.o video.o \ vid_vga.o \ vid_ati_eeprom.o \ vid_ati18800.o vid_ati28800.o \ + vid_ati_mach8.o \ vid_ati_mach64.o vid_ati68860_ramdac.o \ vid_bt48x_ramdac.o \ vid_av9194.o vid_icd2061.o vid_ics2494.o vid_ics2595.o \ @@ -772,7 +775,7 @@ ifeq ($(RTMIDI), y) SNDOBJ += midi_rtmidi.o endif -OBJ := $(MAINOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ +OBJ := $(MAINOBJ) $(CPU808XOBJ) $(CPUOBJ) $(CHIPSETOBJ) $(MCHOBJ) $(DEVOBJ) $(MEMOBJ) \ $(FDDOBJ) $(GAMEOBJ) $(CDROMOBJ) $(ZIPOBJ) $(MOOBJ) $(HDDOBJ) $(MINIVHDOBJ) \ $(NETOBJ) $(PRINTOBJ) $(SCSIOBJ) $(SIOOBJ) $(SNDOBJ) $(VIDOBJ) $(VOODOOOBJ) \ $(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) $(DEVBROBJ) $(MINITRACEOBJ) $(THREADOBJ) @@ -786,15 +789,24 @@ else MWIN := -mwindows endif -LIBS := -lfluidsynth -lslirp -lgomp -lsndfile -lflac -lmp3lame -lmpg123 -lopus -lvorbis -lvorbisenc -logg -ldsound -lshlwapi -lksuser -lreadline -ltermcap -lportaudio -lgmodule-2.0 -lglib-2.0 -lintl -liconv +LIBS := -lfreetype -lfluidsynth -lslirp -lbz2 -lharfbuzz -lgraphite2 -lbrotlidec \ + -lbrotlicommon -lusp10 -lrpcrt4 -lgomp -lsndfile -lflac -lmp3lame -lmpg123 \ + -lopus -lvorbis -lvorbisenc -logg -ldsound -lshlwapi -lksuser -lreadline \ + -ltermcap -lportaudio -lgmodule-2.0 -lglib-2.0 -lintl -liconv ifeq ($(OPENAL), y) - LIBS += $(MWIN) -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32 + LIBS += $(MWIN) -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 \ + -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion \ + -luuid -lws2_32 else ifeq ($(FAUDIO), y) - LIBS += $(MWIN) -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32 + LIBS += $(MWIN) -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 \ + -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion \ + -luuid -lws2_32 else - LIBS += $(MWIN) -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32 + LIBS += $(MWIN) -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 \ + -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid \ + -lws2_32 endif endif